docs-xml: fix pid directory example
[Samba.git] / source3 / smbd / process.c
blobdd26a27ec391eae7ecff4fa57bcfd81c7184242c
1 /*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005-2007
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/>.
21 #include "includes.h"
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"
32 #include "passdb.h"
33 #include "auth.h"
34 #include "messages.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"
42 #include "serverid.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 timed_event *te;
50 struct smb_perfcount_data pcd;
51 uint32_t seqnum;
52 bool encrypted;
53 bool processed;
54 DATA_BLOB buf;
55 DATA_BLOB private_data;
58 static void construct_reply_common(struct smb_request *req, const char *inbuf,
59 char *outbuf);
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)
66 bool ok;
68 if (sconn->smb1.echo_handler.socket_lock_fd == -1) {
69 return true;
72 sconn->smb1.echo_handler.ref_count++;
74 if (sconn->smb1.echo_handler.ref_count > 1) {
75 return true;
78 DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
80 do {
81 ok = fcntl_lock(
82 sconn->smb1.echo_handler.socket_lock_fd,
83 F_SETLKW, 0, 0, F_WRLCK);
84 } while (!ok && (errno == EINTR));
86 if (!ok) {
87 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
88 return false;
91 DEBUG(10,("pid[%d] got for socket lock\n", (int)getpid()));
93 return true;
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)
105 bool ok;
107 if (sconn->smb1.echo_handler.socket_lock_fd == -1) {
108 return true;
111 sconn->smb1.echo_handler.ref_count--;
113 if (sconn->smb1.echo_handler.ref_count > 0) {
114 return true;
117 do {
118 ok = fcntl_lock(
119 sconn->smb1.echo_handler.socket_lock_fd,
120 F_SETLKW, 0, 0, F_UNLCK);
121 } while (!ok && (errno == EINTR));
123 if (!ok) {
124 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
125 return false;
128 DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
130 return true;
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 /****************************************************************************
143 Send an smb to a fd.
144 ****************************************************************************/
146 bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer,
147 bool do_signing, uint32_t seqnum,
148 bool do_encrypt,
149 struct smb_perfcount_data *pcd)
151 size_t len = 0;
152 size_t nwritten=0;
153 ssize_t ret;
154 char *buf_out = buffer;
156 smbd_lock_socket(sconn);
158 if (do_signing) {
159 /* Sign the outgoing packet if required. */
160 srv_calculate_sign_mac(sconn, buf_out, seqnum);
163 if (do_encrypt) {
164 NTSTATUS status = srv_encrypt_buffer(sconn, buffer, &buf_out);
165 if (!NT_STATUS_IS_OK(status)) {
166 DEBUG(0, ("send_smb: SMB encryption failed "
167 "on outgoing packet! Error %s\n",
168 nt_errstr(status) ));
169 goto out;
173 len = smb_len(buf_out) + 4;
175 ret = write_data(sconn->sock, buf_out+nwritten, len - nwritten);
176 if (ret <= 0) {
178 char addr[INET6_ADDRSTRLEN];
180 * Try and give an error message saying what
181 * client failed.
183 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
184 (int)getpid(), (int)len,
185 get_peer_addr(sconn->sock, addr, sizeof(addr)),
186 (int)ret, strerror(errno) ));
188 srv_free_enc_buffer(sconn, buf_out);
189 goto out;
192 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
193 srv_free_enc_buffer(sconn, buf_out);
194 out:
195 SMB_PERFCOUNT_END(pcd);
197 smbd_unlock_socket(sconn);
198 return true;
201 /*******************************************************************
202 Setup the word count and byte count for a smb message.
203 ********************************************************************/
205 int srv_set_message(char *buf,
206 int num_words,
207 int num_bytes,
208 bool zero)
210 if (zero && (num_words || num_bytes)) {
211 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
213 SCVAL(buf,smb_wct,num_words);
214 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
215 smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
216 return (smb_size + num_words*2 + num_bytes);
219 static bool valid_smb_header(struct smbd_server_connection *sconn,
220 const uint8_t *inbuf)
222 if (is_encrypted_packet(sconn, inbuf)) {
223 return true;
226 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
227 * but it just looks weird to call strncmp for this one.
229 return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
232 /* Socket functions for smbd packet processing. */
234 static bool valid_packet_size(size_t len)
237 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
238 * of header. Don't print the error if this fits.... JRA.
241 if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
242 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
243 (unsigned long)len));
244 return false;
246 return true;
249 static NTSTATUS read_packet_remainder(int fd, char *buffer,
250 unsigned int timeout, ssize_t len)
252 NTSTATUS status;
254 if (len <= 0) {
255 return NT_STATUS_OK;
258 status = read_fd_with_timeout(fd, buffer, len, len, timeout, NULL);
259 if (!NT_STATUS_IS_OK(status)) {
260 char addr[INET6_ADDRSTRLEN];
261 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
262 "error = %s.\n",
263 get_peer_addr(fd, addr, sizeof(addr)),
264 nt_errstr(status)));
266 return status;
269 /****************************************************************************
270 Attempt a zerocopy writeX read. We know here that len > smb_size-4
271 ****************************************************************************/
274 * Unfortunately, earlier versions of smbclient/libsmbclient
275 * don't send this "standard" writeX header. I've fixed this
276 * for 3.2 but we'll use the old method with earlier versions.
277 * Windows and CIFSFS at least use this standard size. Not
278 * sure about MacOSX.
281 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
282 (2*14) + /* word count (including bcc) */ \
283 1 /* pad byte */)
285 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
286 const char lenbuf[4],
287 struct smbd_server_connection *sconn,
288 int sock,
289 char **buffer,
290 unsigned int timeout,
291 size_t *p_unread,
292 size_t *len_ret)
294 /* Size of a WRITEX call (+4 byte len). */
295 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
296 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
297 ssize_t toread;
298 NTSTATUS status;
300 memcpy(writeX_header, lenbuf, 4);
302 status = read_fd_with_timeout(
303 sock, writeX_header + 4,
304 STANDARD_WRITE_AND_X_HEADER_SIZE,
305 STANDARD_WRITE_AND_X_HEADER_SIZE,
306 timeout, NULL);
308 if (!NT_STATUS_IS_OK(status)) {
309 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
310 "error = %s.\n",
311 tsocket_address_string(sconn->remote_address,
312 talloc_tos()),
313 nt_errstr(status)));
314 return status;
318 * Ok - now try and see if this is a possible
319 * valid writeX call.
322 if (is_valid_writeX_buffer(sconn, (uint8_t *)writeX_header)) {
324 * If the data offset is beyond what
325 * we've read, drain the extra bytes.
327 uint16_t doff = SVAL(writeX_header,smb_vwv11);
328 ssize_t newlen;
330 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
331 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
332 if (drain_socket(sock, drain) != drain) {
333 smb_panic("receive_smb_raw_talloc_partial_read:"
334 " failed to drain pending bytes");
336 } else {
337 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
340 /* Spoof down the length and null out the bcc. */
341 set_message_bcc(writeX_header, 0);
342 newlen = smb_len(writeX_header);
344 /* Copy the header we've written. */
346 *buffer = (char *)talloc_memdup(mem_ctx,
347 writeX_header,
348 sizeof(writeX_header));
350 if (*buffer == NULL) {
351 DEBUG(0, ("Could not allocate inbuf of length %d\n",
352 (int)sizeof(writeX_header)));
353 return NT_STATUS_NO_MEMORY;
356 /* Work out the remaining bytes. */
357 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
358 *len_ret = newlen + 4;
359 return NT_STATUS_OK;
362 if (!valid_packet_size(len)) {
363 return NT_STATUS_INVALID_PARAMETER;
367 * Not a valid writeX call. Just do the standard
368 * talloc and return.
371 *buffer = talloc_array(mem_ctx, char, len+4);
373 if (*buffer == NULL) {
374 DEBUG(0, ("Could not allocate inbuf of length %d\n",
375 (int)len+4));
376 return NT_STATUS_NO_MEMORY;
379 /* Copy in what we already read. */
380 memcpy(*buffer,
381 writeX_header,
382 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
383 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
385 if(toread > 0) {
386 status = read_packet_remainder(
387 sock,
388 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
389 timeout, toread);
391 if (!NT_STATUS_IS_OK(status)) {
392 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
393 nt_errstr(status)));
394 return status;
398 *len_ret = len + 4;
399 return NT_STATUS_OK;
402 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
403 struct smbd_server_connection *sconn,
404 int sock,
405 char **buffer, unsigned int timeout,
406 size_t *p_unread, size_t *plen)
408 char lenbuf[4];
409 size_t len;
410 int min_recv_size = lp_min_receive_file_size();
411 NTSTATUS status;
413 *p_unread = 0;
415 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
416 &len);
417 if (!NT_STATUS_IS_OK(status)) {
418 return status;
421 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
422 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
423 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
424 !srv_is_signing_active(sconn) &&
425 sconn->smb1.echo_handler.trusted_fde == NULL) {
427 return receive_smb_raw_talloc_partial_read(
428 mem_ctx, lenbuf, sconn, sock, buffer, timeout,
429 p_unread, plen);
432 if (!valid_packet_size(len)) {
433 return NT_STATUS_INVALID_PARAMETER;
437 * The +4 here can't wrap, we've checked the length above already.
440 *buffer = talloc_array(mem_ctx, char, len+4);
442 if (*buffer == NULL) {
443 DEBUG(0, ("Could not allocate inbuf of length %d\n",
444 (int)len+4));
445 return NT_STATUS_NO_MEMORY;
448 memcpy(*buffer, lenbuf, sizeof(lenbuf));
450 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
451 if (!NT_STATUS_IS_OK(status)) {
452 return status;
455 *plen = len + 4;
456 return NT_STATUS_OK;
459 static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx,
460 struct smbd_server_connection *sconn,
461 int sock,
462 char **buffer, unsigned int timeout,
463 size_t *p_unread, bool *p_encrypted,
464 size_t *p_len,
465 uint32_t *seqnum,
466 bool trusted_channel)
468 size_t len = 0;
469 NTSTATUS status;
471 *p_encrypted = false;
473 status = receive_smb_raw_talloc(mem_ctx, sconn, sock, buffer, timeout,
474 p_unread, &len);
475 if (!NT_STATUS_IS_OK(status)) {
476 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
477 ("receive_smb_raw_talloc failed for client %s "
478 "read error = %s.\n",
479 tsocket_address_string(sconn->remote_address,
480 talloc_tos()),
481 nt_errstr(status)) );
482 return status;
485 if (is_encrypted_packet(sconn, (uint8_t *)*buffer)) {
486 status = srv_decrypt_buffer(sconn, *buffer);
487 if (!NT_STATUS_IS_OK(status)) {
488 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
489 "incoming packet! Error %s\n",
490 nt_errstr(status) ));
491 return status;
493 *p_encrypted = true;
496 /* Check the incoming SMB signature. */
497 if (!srv_check_sign_mac(sconn, *buffer, seqnum, trusted_channel)) {
498 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
499 "incoming packet!\n"));
500 return NT_STATUS_INVALID_NETWORK_RESPONSE;
503 *p_len = len;
504 return NT_STATUS_OK;
508 * Initialize a struct smb_request from an inbuf
511 static bool init_smb_request(struct smb_request *req,
512 struct smbd_server_connection *sconn,
513 const uint8 *inbuf,
514 size_t unread_bytes, bool encrypted,
515 uint32_t seqnum)
517 struct smbXsrv_tcon *tcon;
518 NTSTATUS status;
519 NTTIME now;
520 size_t req_size = smb_len(inbuf) + 4;
522 /* Ensure we have at least smb_size bytes. */
523 if (req_size < smb_size) {
524 DEBUG(0,("init_smb_request: invalid request size %u\n",
525 (unsigned int)req_size ));
526 return false;
529 req->request_time = timeval_current();
530 now = timeval_to_nttime(&req->request_time);
532 req->cmd = CVAL(inbuf, smb_com);
533 req->flags2 = SVAL(inbuf, smb_flg2);
534 req->smbpid = SVAL(inbuf, smb_pid);
535 req->mid = (uint64_t)SVAL(inbuf, smb_mid);
536 req->seqnum = seqnum;
537 req->vuid = SVAL(inbuf, smb_uid);
538 req->tid = SVAL(inbuf, smb_tid);
539 req->wct = CVAL(inbuf, smb_wct);
540 req->vwv = (const uint16_t *)(inbuf+smb_vwv);
541 req->buflen = smb_buflen(inbuf);
542 req->buf = (const uint8_t *)smb_buf_const(inbuf);
543 req->unread_bytes = unread_bytes;
544 req->encrypted = encrypted;
545 req->sconn = sconn;
546 status = smb1srv_tcon_lookup(sconn->conn, req->tid, now, &tcon);
547 if (NT_STATUS_IS_OK(status)) {
548 req->conn = tcon->compat;
549 } else {
550 req->conn = NULL;
552 req->chain_fsp = NULL;
553 req->smb2req = NULL;
554 req->priv_paths = NULL;
555 req->chain = NULL;
556 smb_init_perfcount_data(&req->pcd);
558 /* Ensure we have at least wct words and 2 bytes of bcc. */
559 if (smb_size + req->wct*2 > req_size) {
560 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
561 (unsigned int)req->wct,
562 (unsigned int)req_size));
563 return false;
565 /* Ensure bcc is correct. */
566 if (((const uint8_t *)smb_buf_const(inbuf)) + req->buflen > inbuf + req_size) {
567 DEBUG(0,("init_smb_request: invalid bcc number %u "
568 "(wct = %u, size %u)\n",
569 (unsigned int)req->buflen,
570 (unsigned int)req->wct,
571 (unsigned int)req_size));
572 return false;
575 req->outbuf = NULL;
576 return true;
579 static void process_smb(struct smbd_server_connection *conn,
580 uint8_t *inbuf, size_t nread, size_t unread_bytes,
581 uint32_t seqnum, bool encrypted,
582 struct smb_perfcount_data *deferred_pcd);
584 static void smbd_deferred_open_timer(struct event_context *ev,
585 struct timed_event *te,
586 struct timeval _tval,
587 void *private_data)
589 struct pending_message_list *msg = talloc_get_type(private_data,
590 struct pending_message_list);
591 struct smbd_server_connection *sconn = msg->sconn;
592 TALLOC_CTX *mem_ctx = talloc_tos();
593 uint64_t mid = (uint64_t)SVAL(msg->buf.data,smb_mid);
594 uint8_t *inbuf;
596 inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
597 msg->buf.length);
598 if (inbuf == NULL) {
599 exit_server("smbd_deferred_open_timer: talloc failed\n");
600 return;
603 /* We leave this message on the queue so the open code can
604 know this is a retry. */
605 DEBUG(5,("smbd_deferred_open_timer: trigger mid %llu.\n",
606 (unsigned long long)mid ));
608 /* Mark the message as processed so this is not
609 * re-processed in error. */
610 msg->processed = true;
612 process_smb(sconn, inbuf,
613 msg->buf.length, 0,
614 msg->seqnum, msg->encrypted, &msg->pcd);
616 /* If it's still there and was processed, remove it. */
617 msg = get_deferred_open_message_smb(sconn, mid);
618 if (msg && msg->processed) {
619 remove_deferred_open_message_smb(sconn, mid);
623 /****************************************************************************
624 Function to push a message onto the tail of a linked list of smb messages ready
625 for processing.
626 ****************************************************************************/
628 static bool push_queued_message(struct smb_request *req,
629 struct timeval request_time,
630 struct timeval end_time,
631 char *private_data, size_t private_len)
633 int msg_len = smb_len(req->inbuf) + 4;
634 struct pending_message_list *msg;
636 msg = talloc_zero(NULL, struct pending_message_list);
638 if(msg == NULL) {
639 DEBUG(0,("push_message: malloc fail (1)\n"));
640 return False;
642 msg->sconn = req->sconn;
644 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
645 if(msg->buf.data == NULL) {
646 DEBUG(0,("push_message: malloc fail (2)\n"));
647 TALLOC_FREE(msg);
648 return False;
651 msg->request_time = request_time;
652 msg->seqnum = req->seqnum;
653 msg->encrypted = req->encrypted;
654 msg->processed = false;
655 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
657 if (private_data) {
658 msg->private_data = data_blob_talloc(msg, private_data,
659 private_len);
660 if (msg->private_data.data == NULL) {
661 DEBUG(0,("push_message: malloc fail (3)\n"));
662 TALLOC_FREE(msg);
663 return False;
667 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
668 msg,
669 end_time,
670 smbd_deferred_open_timer,
671 msg);
672 if (!msg->te) {
673 DEBUG(0,("push_message: event_add_timed failed\n"));
674 TALLOC_FREE(msg);
675 return false;
678 DLIST_ADD_END(req->sconn->deferred_open_queue, msg,
679 struct pending_message_list *);
681 DEBUG(10,("push_message: pushed message length %u on "
682 "deferred_open_queue\n", (unsigned int)msg_len));
684 return True;
687 /****************************************************************************
688 Function to delete a sharing violation open message by mid.
689 ****************************************************************************/
691 void remove_deferred_open_message_smb(struct smbd_server_connection *sconn,
692 uint64_t mid)
694 struct pending_message_list *pml;
696 if (sconn->using_smb2) {
697 remove_deferred_open_message_smb2(sconn, mid);
698 return;
701 for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
702 if (mid == (uint64_t)SVAL(pml->buf.data,smb_mid)) {
703 DEBUG(10,("remove_deferred_open_message_smb: "
704 "deleting mid %llu len %u\n",
705 (unsigned long long)mid,
706 (unsigned int)pml->buf.length ));
707 DLIST_REMOVE(sconn->deferred_open_queue, pml);
708 TALLOC_FREE(pml);
709 return;
714 /****************************************************************************
715 Move a sharing violation open retry message to the front of the list and
716 schedule it for immediate processing.
717 ****************************************************************************/
719 bool schedule_deferred_open_message_smb(struct smbd_server_connection *sconn,
720 uint64_t mid)
722 struct pending_message_list *pml;
723 int i = 0;
725 if (sconn->using_smb2) {
726 return schedule_deferred_open_message_smb2(sconn, mid);
729 for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
730 uint64_t msg_mid = (uint64_t)SVAL(pml->buf.data,smb_mid);
732 DEBUG(10,("schedule_deferred_open_message_smb: [%d] "
733 "msg_mid = %llu\n",
734 i++,
735 (unsigned long long)msg_mid ));
737 if (mid == msg_mid) {
738 struct timed_event *te;
740 if (pml->processed) {
741 /* A processed message should not be
742 * rescheduled. */
743 DEBUG(0,("schedule_deferred_open_message_smb: LOGIC ERROR "
744 "message mid %llu was already processed\n",
745 (unsigned long long)msg_mid ));
746 continue;
749 DEBUG(10,("schedule_deferred_open_message_smb: "
750 "scheduling mid %llu\n",
751 (unsigned long long)mid ));
753 te = tevent_add_timer(pml->sconn->ev_ctx,
754 pml,
755 timeval_zero(),
756 smbd_deferred_open_timer,
757 pml);
758 if (!te) {
759 DEBUG(10,("schedule_deferred_open_message_smb: "
760 "event_add_timed() failed, "
761 "skipping mid %llu\n",
762 (unsigned long long)msg_mid ));
765 TALLOC_FREE(pml->te);
766 pml->te = te;
767 DLIST_PROMOTE(sconn->deferred_open_queue, pml);
768 return true;
772 DEBUG(10,("schedule_deferred_open_message_smb: failed to "
773 "find message mid %llu\n",
774 (unsigned long long)mid ));
776 return false;
779 /****************************************************************************
780 Return true if this mid is on the deferred queue and was not yet processed.
781 ****************************************************************************/
783 bool open_was_deferred(struct smbd_server_connection *sconn, uint64_t mid)
785 struct pending_message_list *pml;
787 if (sconn->using_smb2) {
788 return open_was_deferred_smb2(sconn, mid);
791 for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
792 if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid && !pml->processed) {
793 return True;
796 return False;
799 /****************************************************************************
800 Return the message queued by this mid.
801 ****************************************************************************/
803 static struct pending_message_list *get_deferred_open_message_smb(
804 struct smbd_server_connection *sconn, uint64_t mid)
806 struct pending_message_list *pml;
808 for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
809 if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid) {
810 return pml;
813 return NULL;
816 /****************************************************************************
817 Get the state data queued by this mid.
818 ****************************************************************************/
820 bool get_deferred_open_message_state(struct smb_request *smbreq,
821 struct timeval *p_request_time,
822 void **pp_state)
824 struct pending_message_list *pml;
826 if (smbreq->sconn->using_smb2) {
827 return get_deferred_open_message_state_smb2(smbreq->smb2req,
828 p_request_time,
829 pp_state);
832 pml = get_deferred_open_message_smb(smbreq->sconn, smbreq->mid);
833 if (!pml) {
834 return false;
836 if (p_request_time) {
837 *p_request_time = pml->request_time;
839 if (pp_state) {
840 *pp_state = (void *)pml->private_data.data;
842 return true;
845 /****************************************************************************
846 Function to push a deferred open smb message onto a linked list of local smb
847 messages ready for processing.
848 ****************************************************************************/
850 bool push_deferred_open_message_smb(struct smb_request *req,
851 struct timeval request_time,
852 struct timeval timeout,
853 struct file_id id,
854 char *private_data, size_t priv_len)
856 struct timeval end_time;
858 if (req->smb2req) {
859 return push_deferred_open_message_smb2(req->smb2req,
860 request_time,
861 timeout,
863 private_data,
864 priv_len);
867 if (req->unread_bytes) {
868 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
869 "unread_bytes = %u\n",
870 (unsigned int)req->unread_bytes ));
871 smb_panic("push_deferred_open_message_smb: "
872 "logic error unread_bytes != 0" );
875 end_time = timeval_sum(&request_time, &timeout);
877 DEBUG(10,("push_deferred_open_message_smb: pushing message "
878 "len %u mid %llu timeout time [%u.%06u]\n",
879 (unsigned int) smb_len(req->inbuf)+4,
880 (unsigned long long)req->mid,
881 (unsigned int)end_time.tv_sec,
882 (unsigned int)end_time.tv_usec));
884 return push_queued_message(req, request_time, end_time,
885 private_data, priv_len);
888 static void smbd_sig_term_handler(struct tevent_context *ev,
889 struct tevent_signal *se,
890 int signum,
891 int count,
892 void *siginfo,
893 void *private_data)
895 exit_server_cleanly("termination signal");
898 void smbd_setup_sig_term_handler(struct smbd_server_connection *sconn)
900 struct tevent_signal *se;
902 se = tevent_add_signal(sconn->ev_ctx,
903 sconn,
904 SIGTERM, 0,
905 smbd_sig_term_handler,
906 sconn);
907 if (!se) {
908 exit_server("failed to setup SIGTERM handler");
912 static void smbd_sig_hup_handler(struct tevent_context *ev,
913 struct tevent_signal *se,
914 int signum,
915 int count,
916 void *siginfo,
917 void *private_data)
919 struct smbd_server_connection *sconn =
920 talloc_get_type_abort(private_data,
921 struct smbd_server_connection);
923 change_to_root_user();
924 DEBUG(1,("Reloading services after SIGHUP\n"));
925 reload_services(sconn, conn_snum_used, false);
928 void smbd_setup_sig_hup_handler(struct smbd_server_connection *sconn)
930 struct tevent_signal *se;
932 se = tevent_add_signal(sconn->ev_ctx,
933 sconn,
934 SIGHUP, 0,
935 smbd_sig_hup_handler,
936 sconn);
937 if (!se) {
938 exit_server("failed to setup SIGHUP handler");
942 static void smbd_conf_updated(struct messaging_context *msg,
943 void *private_data,
944 uint32_t msg_type,
945 struct server_id server_id,
946 DATA_BLOB *data)
948 struct smbd_server_connection *sconn =
949 talloc_get_type_abort(private_data,
950 struct smbd_server_connection);
952 DEBUG(10,("smbd_conf_updated: Got message saying smb.conf was "
953 "updated. Reloading.\n"));
954 change_to_root_user();
955 reload_services(sconn, conn_snum_used, false);
959 * Only allow 5 outstanding trans requests. We're allocating memory, so
960 * prevent a DoS.
963 NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
965 int count = 0;
966 for (; list != NULL; list = list->next) {
968 if (list->mid == mid) {
969 return NT_STATUS_INVALID_PARAMETER;
972 count += 1;
974 if (count > 5) {
975 return NT_STATUS_INSUFFICIENT_RESOURCES;
978 return NT_STATUS_OK;
982 These flags determine some of the permissions required to do an operation
984 Note that I don't set NEED_WRITE on some write operations because they
985 are used by some brain-dead clients when printing, and I don't want to
986 force write permissions on print services.
988 #define AS_USER (1<<0)
989 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
990 #define TIME_INIT (1<<2)
991 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
992 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
993 #define DO_CHDIR (1<<6)
996 define a list of possible SMB messages and their corresponding
997 functions. Any message that has a NULL function is unimplemented -
998 please feel free to contribute implementations!
1000 static const struct smb_message_struct {
1001 const char *name;
1002 void (*fn)(struct smb_request *req);
1003 int flags;
1004 } smb_messages[256] = {
1006 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
1007 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
1008 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
1009 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
1010 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
1011 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
1012 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
1013 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
1014 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
1015 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
1016 /* 0x0a */ { "SMBread",reply_read,AS_USER},
1017 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
1018 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
1019 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
1020 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
1021 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
1022 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
1023 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
1024 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
1025 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
1026 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
1027 /* 0x15 */ { NULL, NULL, 0 },
1028 /* 0x16 */ { NULL, NULL, 0 },
1029 /* 0x17 */ { NULL, NULL, 0 },
1030 /* 0x18 */ { NULL, NULL, 0 },
1031 /* 0x19 */ { NULL, NULL, 0 },
1032 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
1033 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
1034 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
1035 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
1036 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
1037 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
1038 /* 0x20 */ { "SMBwritec", NULL,0},
1039 /* 0x21 */ { NULL, NULL, 0 },
1040 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
1041 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
1042 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
1043 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
1044 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
1045 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
1046 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
1047 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
1048 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
1049 /* 0x2b */ { "SMBecho",reply_echo,0},
1050 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
1051 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
1052 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
1053 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
1054 /* 0x30 */ { NULL, NULL, 0 },
1055 /* 0x31 */ { NULL, NULL, 0 },
1056 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
1057 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
1058 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
1059 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
1060 /* 0x36 */ { NULL, NULL, 0 },
1061 /* 0x37 */ { NULL, NULL, 0 },
1062 /* 0x38 */ { NULL, NULL, 0 },
1063 /* 0x39 */ { NULL, NULL, 0 },
1064 /* 0x3a */ { NULL, NULL, 0 },
1065 /* 0x3b */ { NULL, NULL, 0 },
1066 /* 0x3c */ { NULL, NULL, 0 },
1067 /* 0x3d */ { NULL, NULL, 0 },
1068 /* 0x3e */ { NULL, NULL, 0 },
1069 /* 0x3f */ { NULL, NULL, 0 },
1070 /* 0x40 */ { NULL, NULL, 0 },
1071 /* 0x41 */ { NULL, NULL, 0 },
1072 /* 0x42 */ { NULL, NULL, 0 },
1073 /* 0x43 */ { NULL, NULL, 0 },
1074 /* 0x44 */ { NULL, NULL, 0 },
1075 /* 0x45 */ { NULL, NULL, 0 },
1076 /* 0x46 */ { NULL, NULL, 0 },
1077 /* 0x47 */ { NULL, NULL, 0 },
1078 /* 0x48 */ { NULL, NULL, 0 },
1079 /* 0x49 */ { NULL, NULL, 0 },
1080 /* 0x4a */ { NULL, NULL, 0 },
1081 /* 0x4b */ { NULL, NULL, 0 },
1082 /* 0x4c */ { NULL, NULL, 0 },
1083 /* 0x4d */ { NULL, NULL, 0 },
1084 /* 0x4e */ { NULL, NULL, 0 },
1085 /* 0x4f */ { NULL, NULL, 0 },
1086 /* 0x50 */ { NULL, NULL, 0 },
1087 /* 0x51 */ { NULL, NULL, 0 },
1088 /* 0x52 */ { NULL, NULL, 0 },
1089 /* 0x53 */ { NULL, NULL, 0 },
1090 /* 0x54 */ { NULL, NULL, 0 },
1091 /* 0x55 */ { NULL, NULL, 0 },
1092 /* 0x56 */ { NULL, NULL, 0 },
1093 /* 0x57 */ { NULL, NULL, 0 },
1094 /* 0x58 */ { NULL, NULL, 0 },
1095 /* 0x59 */ { NULL, NULL, 0 },
1096 /* 0x5a */ { NULL, NULL, 0 },
1097 /* 0x5b */ { NULL, NULL, 0 },
1098 /* 0x5c */ { NULL, NULL, 0 },
1099 /* 0x5d */ { NULL, NULL, 0 },
1100 /* 0x5e */ { NULL, NULL, 0 },
1101 /* 0x5f */ { NULL, NULL, 0 },
1102 /* 0x60 */ { NULL, NULL, 0 },
1103 /* 0x61 */ { NULL, NULL, 0 },
1104 /* 0x62 */ { NULL, NULL, 0 },
1105 /* 0x63 */ { NULL, NULL, 0 },
1106 /* 0x64 */ { NULL, NULL, 0 },
1107 /* 0x65 */ { NULL, NULL, 0 },
1108 /* 0x66 */ { NULL, NULL, 0 },
1109 /* 0x67 */ { NULL, NULL, 0 },
1110 /* 0x68 */ { NULL, NULL, 0 },
1111 /* 0x69 */ { NULL, NULL, 0 },
1112 /* 0x6a */ { NULL, NULL, 0 },
1113 /* 0x6b */ { NULL, NULL, 0 },
1114 /* 0x6c */ { NULL, NULL, 0 },
1115 /* 0x6d */ { NULL, NULL, 0 },
1116 /* 0x6e */ { NULL, NULL, 0 },
1117 /* 0x6f */ { NULL, NULL, 0 },
1118 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1119 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1120 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1121 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1122 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1123 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1124 /* 0x76 */ { NULL, NULL, 0 },
1125 /* 0x77 */ { NULL, NULL, 0 },
1126 /* 0x78 */ { NULL, NULL, 0 },
1127 /* 0x79 */ { NULL, NULL, 0 },
1128 /* 0x7a */ { NULL, NULL, 0 },
1129 /* 0x7b */ { NULL, NULL, 0 },
1130 /* 0x7c */ { NULL, NULL, 0 },
1131 /* 0x7d */ { NULL, NULL, 0 },
1132 /* 0x7e */ { NULL, NULL, 0 },
1133 /* 0x7f */ { NULL, NULL, 0 },
1134 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1135 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1136 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1137 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1138 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1139 /* 0x85 */ { NULL, NULL, 0 },
1140 /* 0x86 */ { NULL, NULL, 0 },
1141 /* 0x87 */ { NULL, NULL, 0 },
1142 /* 0x88 */ { NULL, NULL, 0 },
1143 /* 0x89 */ { NULL, NULL, 0 },
1144 /* 0x8a */ { NULL, NULL, 0 },
1145 /* 0x8b */ { NULL, NULL, 0 },
1146 /* 0x8c */ { NULL, NULL, 0 },
1147 /* 0x8d */ { NULL, NULL, 0 },
1148 /* 0x8e */ { NULL, NULL, 0 },
1149 /* 0x8f */ { NULL, NULL, 0 },
1150 /* 0x90 */ { NULL, NULL, 0 },
1151 /* 0x91 */ { NULL, NULL, 0 },
1152 /* 0x92 */ { NULL, NULL, 0 },
1153 /* 0x93 */ { NULL, NULL, 0 },
1154 /* 0x94 */ { NULL, NULL, 0 },
1155 /* 0x95 */ { NULL, NULL, 0 },
1156 /* 0x96 */ { NULL, NULL, 0 },
1157 /* 0x97 */ { NULL, NULL, 0 },
1158 /* 0x98 */ { NULL, NULL, 0 },
1159 /* 0x99 */ { NULL, NULL, 0 },
1160 /* 0x9a */ { NULL, NULL, 0 },
1161 /* 0x9b */ { NULL, NULL, 0 },
1162 /* 0x9c */ { NULL, NULL, 0 },
1163 /* 0x9d */ { NULL, NULL, 0 },
1164 /* 0x9e */ { NULL, NULL, 0 },
1165 /* 0x9f */ { NULL, NULL, 0 },
1166 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1167 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1168 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1169 /* 0xa3 */ { NULL, NULL, 0 },
1170 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1171 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1172 /* 0xa6 */ { NULL, NULL, 0 },
1173 /* 0xa7 */ { NULL, NULL, 0 },
1174 /* 0xa8 */ { NULL, NULL, 0 },
1175 /* 0xa9 */ { NULL, NULL, 0 },
1176 /* 0xaa */ { NULL, NULL, 0 },
1177 /* 0xab */ { NULL, NULL, 0 },
1178 /* 0xac */ { NULL, NULL, 0 },
1179 /* 0xad */ { NULL, NULL, 0 },
1180 /* 0xae */ { NULL, NULL, 0 },
1181 /* 0xaf */ { NULL, NULL, 0 },
1182 /* 0xb0 */ { NULL, NULL, 0 },
1183 /* 0xb1 */ { NULL, NULL, 0 },
1184 /* 0xb2 */ { NULL, NULL, 0 },
1185 /* 0xb3 */ { NULL, NULL, 0 },
1186 /* 0xb4 */ { NULL, NULL, 0 },
1187 /* 0xb5 */ { NULL, NULL, 0 },
1188 /* 0xb6 */ { NULL, NULL, 0 },
1189 /* 0xb7 */ { NULL, NULL, 0 },
1190 /* 0xb8 */ { NULL, NULL, 0 },
1191 /* 0xb9 */ { NULL, NULL, 0 },
1192 /* 0xba */ { NULL, NULL, 0 },
1193 /* 0xbb */ { NULL, NULL, 0 },
1194 /* 0xbc */ { NULL, NULL, 0 },
1195 /* 0xbd */ { NULL, NULL, 0 },
1196 /* 0xbe */ { NULL, NULL, 0 },
1197 /* 0xbf */ { NULL, NULL, 0 },
1198 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1199 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1200 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1201 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1202 /* 0xc4 */ { NULL, NULL, 0 },
1203 /* 0xc5 */ { NULL, NULL, 0 },
1204 /* 0xc6 */ { NULL, NULL, 0 },
1205 /* 0xc7 */ { NULL, NULL, 0 },
1206 /* 0xc8 */ { NULL, NULL, 0 },
1207 /* 0xc9 */ { NULL, NULL, 0 },
1208 /* 0xca */ { NULL, NULL, 0 },
1209 /* 0xcb */ { NULL, NULL, 0 },
1210 /* 0xcc */ { NULL, NULL, 0 },
1211 /* 0xcd */ { NULL, NULL, 0 },
1212 /* 0xce */ { NULL, NULL, 0 },
1213 /* 0xcf */ { NULL, NULL, 0 },
1214 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1215 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1216 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1217 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1218 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1219 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1220 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1221 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1222 /* 0xd8 */ { NULL, NULL, 0 },
1223 /* 0xd9 */ { NULL, NULL, 0 },
1224 /* 0xda */ { NULL, NULL, 0 },
1225 /* 0xdb */ { NULL, NULL, 0 },
1226 /* 0xdc */ { NULL, NULL, 0 },
1227 /* 0xdd */ { NULL, NULL, 0 },
1228 /* 0xde */ { NULL, NULL, 0 },
1229 /* 0xdf */ { NULL, NULL, 0 },
1230 /* 0xe0 */ { NULL, NULL, 0 },
1231 /* 0xe1 */ { NULL, NULL, 0 },
1232 /* 0xe2 */ { NULL, NULL, 0 },
1233 /* 0xe3 */ { NULL, NULL, 0 },
1234 /* 0xe4 */ { NULL, NULL, 0 },
1235 /* 0xe5 */ { NULL, NULL, 0 },
1236 /* 0xe6 */ { NULL, NULL, 0 },
1237 /* 0xe7 */ { NULL, NULL, 0 },
1238 /* 0xe8 */ { NULL, NULL, 0 },
1239 /* 0xe9 */ { NULL, NULL, 0 },
1240 /* 0xea */ { NULL, NULL, 0 },
1241 /* 0xeb */ { NULL, NULL, 0 },
1242 /* 0xec */ { NULL, NULL, 0 },
1243 /* 0xed */ { NULL, NULL, 0 },
1244 /* 0xee */ { NULL, NULL, 0 },
1245 /* 0xef */ { NULL, NULL, 0 },
1246 /* 0xf0 */ { NULL, NULL, 0 },
1247 /* 0xf1 */ { NULL, NULL, 0 },
1248 /* 0xf2 */ { NULL, NULL, 0 },
1249 /* 0xf3 */ { NULL, NULL, 0 },
1250 /* 0xf4 */ { NULL, NULL, 0 },
1251 /* 0xf5 */ { NULL, NULL, 0 },
1252 /* 0xf6 */ { NULL, NULL, 0 },
1253 /* 0xf7 */ { NULL, NULL, 0 },
1254 /* 0xf8 */ { NULL, NULL, 0 },
1255 /* 0xf9 */ { NULL, NULL, 0 },
1256 /* 0xfa */ { NULL, NULL, 0 },
1257 /* 0xfb */ { NULL, NULL, 0 },
1258 /* 0xfc */ { NULL, NULL, 0 },
1259 /* 0xfd */ { NULL, NULL, 0 },
1260 /* 0xfe */ { NULL, NULL, 0 },
1261 /* 0xff */ { NULL, NULL, 0 }
1265 /*******************************************************************
1266 allocate and initialize a reply packet
1267 ********************************************************************/
1269 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1270 const char *inbuf, char **outbuf, uint8_t num_words,
1271 uint32_t num_bytes)
1274 * Protect against integer wrap
1276 if ((num_bytes > 0xffffff)
1277 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1278 char *msg;
1279 if (asprintf(&msg, "num_bytes too large: %u",
1280 (unsigned)num_bytes) == -1) {
1281 msg = discard_const_p(char, "num_bytes too large");
1283 smb_panic(msg);
1286 *outbuf = talloc_array(mem_ctx, char,
1287 smb_size + num_words*2 + num_bytes);
1288 if (*outbuf == NULL) {
1289 return false;
1292 construct_reply_common(req, inbuf, *outbuf);
1293 srv_set_message(*outbuf, num_words, num_bytes, false);
1295 * Zero out the word area, the caller has to take care of the bcc area
1296 * himself
1298 if (num_words != 0) {
1299 memset(*outbuf + smb_vwv0, 0, num_words*2);
1302 return true;
1305 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1307 char *outbuf;
1308 if (!create_outbuf(req, req, (const char *)req->inbuf, &outbuf, num_words,
1309 num_bytes)) {
1310 smb_panic("could not allocate output buffer\n");
1312 req->outbuf = (uint8_t *)outbuf;
1316 /*******************************************************************
1317 Dump a packet to a file.
1318 ********************************************************************/
1320 static void smb_dump(const char *name, int type, const char *data)
1322 size_t len;
1323 int fd, i;
1324 char *fname = NULL;
1325 if (DEBUGLEVEL < 50) {
1326 return;
1329 len = smb_len_tcp(data)+4;
1330 for (i=1;i<100;i++) {
1331 fname = talloc_asprintf(talloc_tos(),
1332 "/tmp/%s.%d.%s",
1333 name,
1335 type ? "req" : "resp");
1336 if (fname == NULL) {
1337 return;
1339 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1340 if (fd != -1 || errno != EEXIST) break;
1341 TALLOC_FREE(fname);
1343 if (fd != -1) {
1344 ssize_t ret = write(fd, data, len);
1345 if (ret != len)
1346 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1347 close(fd);
1348 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1350 TALLOC_FREE(fname);
1353 /****************************************************************************
1354 Prepare everything for calling the actual request function, and potentially
1355 call the request function via the "new" interface.
1357 Return False if the "legacy" function needs to be called, everything is
1358 prepared.
1360 Return True if we're done.
1362 I know this API sucks, but it is the one with the least code change I could
1363 find.
1364 ****************************************************************************/
1366 static connection_struct *switch_message(uint8 type, struct smb_request *req)
1368 int flags;
1369 uint64_t session_tag;
1370 connection_struct *conn = NULL;
1371 struct smbd_server_connection *sconn = req->sconn;
1372 NTTIME now = timeval_to_nttime(&req->request_time);
1373 struct smbXsrv_session *session = NULL;
1374 NTSTATUS status;
1376 errno = 0;
1378 if (smb_messages[type].fn == NULL) {
1379 DEBUG(0,("Unknown message type %d!\n",type));
1380 smb_dump("Unknown", 1, (const char *)req->inbuf);
1381 reply_unknown_new(req, type);
1382 return NULL;
1385 flags = smb_messages[type].flags;
1387 /* In share mode security we must ignore the vuid. */
1388 session_tag = req->vuid;
1389 conn = req->conn;
1391 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1392 (int)getpid(), (unsigned long)conn));
1394 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1396 /* Ensure this value is replaced in the incoming packet. */
1397 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1400 * Ensure the correct username is in current_user_info. This is a
1401 * really ugly bugfix for problems with multiple session_setup_and_X's
1402 * being done and allowing %U and %G substitutions to work correctly.
1403 * There is a reason this code is done here, don't move it unless you
1404 * know what you're doing... :-).
1405 * JRA.
1409 * lookup an existing session
1411 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1412 * here, the main check is still in change_to_user()
1414 status = smb1srv_session_lookup(sconn->conn,
1415 session_tag,
1416 now,
1417 &session);
1418 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1419 switch (type) {
1420 case SMBsesssetupX:
1421 status = NT_STATUS_OK;
1422 break;
1423 default:
1424 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1425 (unsigned long long)session_tag,
1426 (unsigned long long)req->mid));
1427 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1428 return conn;
1432 if (session_tag != sconn->smb1.sessions.last_session_tag) {
1433 struct user_struct *vuser = NULL;
1435 sconn->smb1.sessions.last_session_tag = session_tag;
1436 if (session) {
1437 vuser = session->compat;
1439 if (vuser) {
1440 set_current_user_info(
1441 vuser->session_info->unix_info->sanitized_username,
1442 vuser->session_info->unix_info->unix_name,
1443 vuser->session_info->info->domain_name);
1447 /* Does this call need to be run as the connected user? */
1448 if (flags & AS_USER) {
1450 /* Does this call need a valid tree connection? */
1451 if (!conn) {
1453 * Amazingly, the error code depends on the command
1454 * (from Samba4).
1456 if (type == SMBntcreateX) {
1457 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1458 } else {
1459 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1461 return NULL;
1464 if (!change_to_user(conn,session_tag)) {
1465 DEBUG(0, ("Error: Could not change to user. Removing "
1466 "deferred open, mid=%llu.\n",
1467 (unsigned long long)req->mid));
1468 reply_force_doserror(req, ERRSRV, ERRbaduid);
1469 return conn;
1472 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1474 /* Does it need write permission? */
1475 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1476 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1477 return conn;
1480 /* IPC services are limited */
1481 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1482 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1483 return conn;
1485 } else {
1486 /* This call needs to be run as root */
1487 change_to_root_user();
1490 /* load service specific parameters */
1491 if (conn) {
1492 if (req->encrypted) {
1493 conn->encrypted_tid = true;
1494 /* encrypted required from now on. */
1495 conn->encrypt_level = Required;
1496 } else if (ENCRYPTION_REQUIRED(conn)) {
1497 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1498 exit_server_cleanly("encryption required "
1499 "on connection");
1500 return conn;
1504 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1505 (flags & (AS_USER|DO_CHDIR)
1506 ?True:False))) {
1507 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1508 return conn;
1510 conn->num_smb_operations++;
1514 * Does this protocol need to be run as guest? (Only archane
1515 * messenger service requests have this...)
1517 if (flags & AS_GUEST) {
1518 char *raddr;
1519 bool ok;
1521 if (!change_to_guest()) {
1522 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1523 return conn;
1526 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
1527 talloc_tos());
1528 if (raddr == NULL) {
1529 reply_nterror(req, NT_STATUS_NO_MEMORY);
1530 return conn;
1534 * Haven't we checked this in smbd_process already???
1537 ok = allow_access(lp_hostsdeny(-1), lp_hostsallow(-1),
1538 sconn->remote_hostname, raddr);
1539 TALLOC_FREE(raddr);
1541 if (!ok) {
1542 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1543 return conn;
1547 smb_messages[type].fn(req);
1548 return req->conn;
1551 /****************************************************************************
1552 Construct a reply to the incoming packet.
1553 ****************************************************************************/
1555 static void construct_reply(struct smbd_server_connection *sconn,
1556 char *inbuf, int size, size_t unread_bytes,
1557 uint32_t seqnum, bool encrypted,
1558 struct smb_perfcount_data *deferred_pcd)
1560 connection_struct *conn;
1561 struct smb_request *req;
1563 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1564 smb_panic("could not allocate smb_request");
1567 if (!init_smb_request(req, sconn, (uint8 *)inbuf, unread_bytes,
1568 encrypted, seqnum)) {
1569 exit_server_cleanly("Invalid SMB request");
1572 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1574 /* we popped this message off the queue - keep original perf data */
1575 if (deferred_pcd)
1576 req->pcd = *deferred_pcd;
1577 else {
1578 SMB_PERFCOUNT_START(&req->pcd);
1579 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1580 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1583 conn = switch_message(req->cmd, req);
1585 if (req->outbuf == NULL) {
1586 return;
1589 if (CVAL(req->outbuf,0) == 0) {
1590 show_msg((char *)req->outbuf);
1593 if (!srv_send_smb(req->sconn,
1594 (char *)req->outbuf,
1595 true, req->seqnum+1,
1596 IS_CONN_ENCRYPTED(conn)||req->encrypted,
1597 &req->pcd)) {
1598 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1601 TALLOC_FREE(req);
1603 return;
1606 static void construct_reply_chain(struct smbd_server_connection *sconn,
1607 char *inbuf, int size, uint32_t seqnum,
1608 bool encrypted,
1609 struct smb_perfcount_data *deferred_pcd)
1611 struct smb_request **reqs = NULL;
1612 struct smb_request *req;
1613 unsigned num_reqs;
1614 bool ok;
1616 ok = smb1_parse_chain(talloc_tos(), (uint8_t *)inbuf, sconn, encrypted,
1617 seqnum, &reqs, &num_reqs);
1618 if (!ok) {
1619 char errbuf[smb_size];
1620 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1621 __LINE__, __FILE__);
1622 if (!srv_send_smb(sconn, errbuf, true, seqnum, encrypted,
1623 NULL)) {
1624 exit_server_cleanly("construct_reply_chain: "
1625 "srv_send_smb failed.");
1627 return;
1630 req = reqs[0];
1631 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1633 req->conn = switch_message(req->cmd, req);
1635 if (req->outbuf == NULL) {
1637 * Request has suspended itself, will come
1638 * back here.
1640 return;
1642 smb_request_done(req);
1646 * To be called from an async SMB handler that is potentially chained
1647 * when it is finished for shipping.
1650 void smb_request_done(struct smb_request *req)
1652 struct smb_request **reqs = NULL;
1653 struct smb_request *first_req;
1654 size_t i, num_reqs, next_index;
1655 NTSTATUS status;
1657 if (req->chain == NULL) {
1658 first_req = req;
1659 goto shipit;
1662 reqs = req->chain;
1663 num_reqs = talloc_array_length(reqs);
1665 for (i=0; i<num_reqs; i++) {
1666 if (reqs[i] == req) {
1667 break;
1670 if (i == num_reqs) {
1672 * Invalid chain, should not happen
1674 status = NT_STATUS_INTERNAL_ERROR;
1675 goto error;
1677 next_index = i+1;
1679 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1680 struct smb_request *next = reqs[next_index];
1681 struct smbXsrv_tcon *tcon;
1682 NTTIME now = timeval_to_nttime(&req->request_time);
1684 next->vuid = SVAL(req->outbuf, smb_uid);
1685 next->tid = SVAL(req->outbuf, smb_tid);
1686 status = smb1srv_tcon_lookup(req->sconn->conn, req->tid,
1687 now, &tcon);
1688 if (NT_STATUS_IS_OK(status)) {
1689 req->conn = tcon->compat;
1690 } else {
1691 req->conn = NULL;
1693 next->chain_fsp = req->chain_fsp;
1694 next->inbuf = (uint8_t *)req->inbuf;
1696 req = next;
1697 req->conn = switch_message(req->cmd, req);
1699 if (req->outbuf == NULL) {
1701 * Request has suspended itself, will come
1702 * back here.
1704 return;
1706 next_index += 1;
1709 first_req = reqs[0];
1711 for (i=1; i<next_index; i++) {
1712 bool ok;
1714 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1715 if (!ok) {
1716 status = NT_STATUS_INTERNAL_ERROR;
1717 goto error;
1721 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1722 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
1725 * This scary statement intends to set the
1726 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1727 * to the value last_req->outbuf carries
1729 SSVAL(first_req->outbuf, smb_flg2,
1730 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1731 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1734 * Transfer the error codes from the subrequest to the main one
1736 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1737 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1739 _smb_setlen_large(
1740 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1742 shipit:
1743 if (!srv_send_smb(first_req->sconn,
1744 (char *)first_req->outbuf,
1745 true, first_req->seqnum+1,
1746 IS_CONN_ENCRYPTED(req->conn)||first_req->encrypted,
1747 &first_req->pcd)) {
1748 exit_server_cleanly("construct_reply_chain: srv_send_smb "
1749 "failed.");
1751 TALLOC_FREE(req); /* non-chained case */
1752 TALLOC_FREE(reqs); /* chained case */
1753 return;
1755 error:
1757 char errbuf[smb_size];
1758 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1759 if (!srv_send_smb(req->sconn, errbuf, true,
1760 req->seqnum+1, req->encrypted,
1761 NULL)) {
1762 exit_server_cleanly("construct_reply_chain: "
1763 "srv_send_smb failed.");
1766 TALLOC_FREE(req); /* non-chained case */
1767 TALLOC_FREE(reqs); /* chained case */
1770 /****************************************************************************
1771 Process an smb from the client
1772 ****************************************************************************/
1773 static void process_smb(struct smbd_server_connection *sconn,
1774 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1775 uint32_t seqnum, bool encrypted,
1776 struct smb_perfcount_data *deferred_pcd)
1778 int msg_type = CVAL(inbuf,0);
1780 DO_PROFILE_INC(smb_count);
1782 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1783 smb_len(inbuf) ) );
1784 DEBUG(3, ("Transaction %d of length %d (%u toread)\n",
1785 sconn->trans_num, (int)nread, (unsigned int)unread_bytes));
1787 if (msg_type != NBSSmessage) {
1789 * NetBIOS session request, keepalive, etc.
1791 reply_special(sconn, (char *)inbuf, nread);
1792 goto done;
1795 if (sconn->using_smb2) {
1796 /* At this point we're not really using smb2,
1797 * we make the decision here.. */
1798 if (smbd_is_smb2_header(inbuf, nread)) {
1799 smbd_smb2_first_negprot(sconn, inbuf, nread);
1800 return;
1801 } else if (nread >= smb_size && valid_smb_header(sconn, inbuf)
1802 && CVAL(inbuf, smb_com) != 0x72) {
1803 /* This is a non-negprot SMB1 packet.
1804 Disable SMB2 from now on. */
1805 sconn->using_smb2 = false;
1809 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1810 * so subtract 4 from it. */
1811 if ((nread < (smb_size - 4)) || !valid_smb_header(sconn, inbuf)) {
1812 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1813 smb_len(inbuf)));
1815 /* special magic for immediate exit */
1816 if ((nread == 9) &&
1817 (IVAL(inbuf, 4) == 0x74697865) &&
1818 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1819 uint8_t exitcode = CVAL(inbuf, 8);
1820 DEBUG(1, ("Exiting immediately with code %d\n",
1821 (int)exitcode));
1822 exit(exitcode);
1825 exit_server_cleanly("Non-SMB packet");
1828 show_msg((char *)inbuf);
1830 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1831 construct_reply_chain(sconn, (char *)inbuf, nread,
1832 seqnum, encrypted, deferred_pcd);
1833 } else {
1834 construct_reply(sconn, (char *)inbuf, nread, unread_bytes,
1835 seqnum, encrypted, deferred_pcd);
1838 sconn->trans_num++;
1840 done:
1841 sconn->num_requests++;
1843 /* The timeout_processing function isn't run nearly
1844 often enough to implement 'max log size' without
1845 overrunning the size of the file by many megabytes.
1846 This is especially true if we are running at debug
1847 level 10. Checking every 50 SMBs is a nice
1848 tradeoff of performance vs log file size overrun. */
1850 if ((sconn->num_requests % 50) == 0 &&
1851 need_to_check_log_size()) {
1852 change_to_root_user();
1853 check_log_size();
1857 /****************************************************************************
1858 Return a string containing the function name of a SMB command.
1859 ****************************************************************************/
1861 const char *smb_fn_name(int type)
1863 const char *unknown_name = "SMBunknown";
1865 if (smb_messages[type].name == NULL)
1866 return(unknown_name);
1868 return(smb_messages[type].name);
1871 /****************************************************************************
1872 Helper functions for contruct_reply.
1873 ****************************************************************************/
1875 void add_to_common_flags2(uint32 v)
1877 common_flags2 |= v;
1880 void remove_from_common_flags2(uint32 v)
1882 common_flags2 &= ~v;
1885 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1886 char *outbuf)
1888 uint16_t in_flags2 = SVAL(inbuf,smb_flg2);
1889 uint16_t out_flags2 = common_flags2;
1891 out_flags2 |= in_flags2 & FLAGS2_UNICODE_STRINGS;
1892 out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES;
1893 out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
1895 srv_set_message(outbuf,0,0,false);
1897 SCVAL(outbuf, smb_com, req->cmd);
1898 SIVAL(outbuf,smb_rcls,0);
1899 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1900 SSVAL(outbuf,smb_flg2, out_flags2);
1901 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1902 memcpy(outbuf+smb_ss_field, inbuf+smb_ss_field, 8);
1904 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1905 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1906 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1907 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1910 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1912 construct_reply_common(req, (const char *)req->inbuf, outbuf);
1916 * @brief Find the smb_cmd offset of the last command pushed
1917 * @param[in] buf The buffer we're building up
1918 * @retval Where can we put our next andx cmd?
1920 * While chaining requests, the "next" request we're looking at needs to put
1921 * its SMB_Command before the data the previous request already built up added
1922 * to the chain. Find the offset to the place where we have to put our cmd.
1925 static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1927 uint8_t cmd;
1928 size_t ofs;
1930 cmd = CVAL(buf, smb_com);
1932 if (!is_andx_req(cmd)) {
1933 return false;
1936 ofs = smb_vwv0;
1938 while (CVAL(buf, ofs) != 0xff) {
1940 if (!is_andx_req(CVAL(buf, ofs))) {
1941 return false;
1945 * ofs is from start of smb header, so add the 4 length
1946 * bytes. The next cmd is right after the wct field.
1948 ofs = SVAL(buf, ofs+2) + 4 + 1;
1950 if (ofs+4 >= talloc_get_size(buf)) {
1951 return false;
1955 *pofs = ofs;
1956 return true;
1960 * @brief Do the smb chaining at a buffer level
1961 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1962 * @param[in] andx_buf Buffer to be appended
1965 static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1967 uint8_t smb_command = CVAL(andx_buf, smb_com);
1968 uint8_t wct = CVAL(andx_buf, smb_wct);
1969 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1970 uint32_t num_bytes = smb_buflen(andx_buf);
1971 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1973 uint8_t *outbuf;
1974 size_t old_size, new_size;
1975 size_t ofs;
1976 size_t chain_padding = 0;
1977 size_t andx_cmd_ofs;
1980 old_size = talloc_get_size(*poutbuf);
1982 if ((old_size % 4) != 0) {
1984 * Align the wct field of subsequent requests to a 4-byte
1985 * boundary
1987 chain_padding = 4 - (old_size % 4);
1991 * After the old request comes the new wct field (1 byte), the vwv's
1992 * and the num_bytes field.
1995 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1996 new_size += num_bytes;
1998 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1999 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
2000 (unsigned)new_size));
2001 return false;
2004 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
2005 if (outbuf == NULL) {
2006 DEBUG(0, ("talloc failed\n"));
2007 return false;
2009 *poutbuf = outbuf;
2011 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
2012 DEBUG(1, ("invalid command chain\n"));
2013 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
2014 return false;
2017 if (chain_padding != 0) {
2018 memset(outbuf + old_size, 0, chain_padding);
2019 old_size += chain_padding;
2022 SCVAL(outbuf, andx_cmd_ofs, smb_command);
2023 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
2025 ofs = old_size;
2028 * Push the chained request:
2030 * wct field
2033 SCVAL(outbuf, ofs, wct);
2034 ofs += 1;
2037 * vwv array
2040 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
2043 * HACK ALERT
2045 * Read&X has an offset into its data buffer at
2046 * vwv[6]. reply_read_andx has no idea anymore that it's
2047 * running from within a chain, so we have to fix up the
2048 * offset here.
2050 * Although it looks disgusting at this place, I want to keep
2051 * it here. The alternative would be to push knowledge about
2052 * the andx chain down into read&x again.
2055 if (smb_command == SMBreadX) {
2056 uint8_t *bytes_addr;
2058 if (wct < 7) {
2060 * Invalid read&x response
2062 return false;
2065 bytes_addr = outbuf + ofs /* vwv start */
2066 + sizeof(uint16_t) * wct /* vwv array */
2067 + sizeof(uint16_t); /* bcc */
2069 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
2070 bytes_addr - outbuf - 4);
2073 ofs += sizeof(uint16_t) * wct;
2076 * bcc (byte count)
2079 SSVAL(outbuf, ofs, num_bytes);
2080 ofs += sizeof(uint16_t);
2083 * The bytes field
2086 memcpy(outbuf + ofs, bytes, num_bytes);
2088 return true;
2091 bool smb1_is_chain(const uint8_t *buf)
2093 uint8_t cmd, wct, andx_cmd;
2095 cmd = CVAL(buf, smb_com);
2096 if (!is_andx_req(cmd)) {
2097 return false;
2099 wct = CVAL(buf, smb_wct);
2100 if (wct < 2) {
2101 return false;
2103 andx_cmd = CVAL(buf, smb_vwv);
2104 return (andx_cmd != 0xFF);
2107 bool smb1_walk_chain(const uint8_t *buf,
2108 bool (*fn)(uint8_t cmd,
2109 uint8_t wct, const uint16_t *vwv,
2110 uint16_t num_bytes, const uint8_t *bytes,
2111 void *private_data),
2112 void *private_data)
2114 size_t smblen = smb_len(buf);
2115 const char *smb_buf = smb_base(buf);
2116 uint8_t cmd, chain_cmd;
2117 uint8_t wct;
2118 const uint16_t *vwv;
2119 uint16_t num_bytes;
2120 const uint8_t *bytes;
2122 cmd = CVAL(buf, smb_com);
2123 wct = CVAL(buf, smb_wct);
2124 vwv = (const uint16_t *)(buf + smb_vwv);
2125 num_bytes = smb_buflen(buf);
2126 bytes = (uint8_t *)smb_buf_const(buf);
2128 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
2129 return false;
2132 if (!is_andx_req(cmd)) {
2133 return true;
2135 if (wct < 2) {
2136 return false;
2139 chain_cmd = CVAL(vwv, 0);
2141 while (chain_cmd != 0xff) {
2142 uint32_t chain_offset; /* uint32_t to avoid overflow */
2143 size_t length_needed;
2144 ptrdiff_t vwv_offset;
2146 chain_offset = SVAL(vwv+1, 0);
2149 * Check if the client tries to fool us. The chain
2150 * offset needs to point beyond the current request in
2151 * the chain, it needs to strictly grow. Otherwise we
2152 * might be tricked into an endless loop always
2153 * processing the same request over and over again. We
2154 * used to assume that vwv and the byte buffer array
2155 * in a chain are always attached, but OS/2 the
2156 * Write&X/Read&X chain puts the Read&X vwv array
2157 * right behind the Write&X vwv chain. The Write&X bcc
2158 * array is put behind the Read&X vwv array. So now we
2159 * check whether the chain offset points strictly
2160 * behind the previous vwv array. req->buf points
2161 * right after the vwv array of the previous
2162 * request. See
2163 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
2164 * more information.
2167 vwv_offset = ((const char *)vwv - smb_buf);
2168 if (chain_offset <= vwv_offset) {
2169 return false;
2173 * Next check: Make sure the chain offset does not
2174 * point beyond the overall smb request length.
2177 length_needed = chain_offset+1; /* wct */
2178 if (length_needed > smblen) {
2179 return false;
2183 * Now comes the pointer magic. Goal here is to set up
2184 * vwv and buf correctly again. The chain offset (the
2185 * former vwv[1]) points at the new wct field.
2188 wct = CVAL(smb_buf, chain_offset);
2190 if (is_andx_req(chain_cmd) && (wct < 2)) {
2191 return false;
2195 * Next consistency check: Make the new vwv array fits
2196 * in the overall smb request.
2199 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
2200 if (length_needed > smblen) {
2201 return false;
2203 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
2206 * Now grab the new byte buffer....
2209 num_bytes = SVAL(vwv+wct, 0);
2212 * .. and check that it fits.
2215 length_needed += num_bytes;
2216 if (length_needed > smblen) {
2217 return false;
2219 bytes = (const uint8_t *)(vwv+wct+1);
2221 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
2222 return false;
2225 if (!is_andx_req(chain_cmd)) {
2226 return true;
2228 chain_cmd = CVAL(vwv, 0);
2230 return true;
2233 static bool smb1_chain_length_cb(uint8_t cmd,
2234 uint8_t wct, const uint16_t *vwv,
2235 uint16_t num_bytes, const uint8_t *bytes,
2236 void *private_data)
2238 unsigned *count = (unsigned *)private_data;
2239 *count += 1;
2240 return true;
2243 unsigned smb1_chain_length(const uint8_t *buf)
2245 unsigned count = 0;
2247 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
2248 return 0;
2250 return count;
2253 struct smb1_parse_chain_state {
2254 TALLOC_CTX *mem_ctx;
2255 const uint8_t *buf;
2256 struct smbd_server_connection *sconn;
2257 bool encrypted;
2258 uint32_t seqnum;
2260 struct smb_request **reqs;
2261 unsigned num_reqs;
2264 static bool smb1_parse_chain_cb(uint8_t cmd,
2265 uint8_t wct, const uint16_t *vwv,
2266 uint16_t num_bytes, const uint8_t *bytes,
2267 void *private_data)
2269 struct smb1_parse_chain_state *state =
2270 (struct smb1_parse_chain_state *)private_data;
2271 struct smb_request **reqs;
2272 struct smb_request *req;
2273 bool ok;
2275 reqs = talloc_realloc(state->mem_ctx, state->reqs,
2276 struct smb_request *, state->num_reqs+1);
2277 if (reqs == NULL) {
2278 return false;
2280 state->reqs = reqs;
2282 req = talloc(reqs, struct smb_request);
2283 if (req == NULL) {
2284 return false;
2287 ok = init_smb_request(req, state->sconn, state->buf, 0,
2288 state->encrypted, state->seqnum);
2289 if (!ok) {
2290 return false;
2292 req->cmd = cmd;
2293 req->wct = wct;
2294 req->vwv = vwv;
2295 req->buflen = num_bytes;
2296 req->buf = bytes;
2298 reqs[state->num_reqs] = req;
2299 state->num_reqs += 1;
2300 return true;
2303 bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
2304 struct smbd_server_connection *sconn,
2305 bool encrypted, uint32_t seqnum,
2306 struct smb_request ***reqs, unsigned *num_reqs)
2308 struct smb1_parse_chain_state state;
2309 unsigned i;
2311 state.mem_ctx = mem_ctx;
2312 state.buf = buf;
2313 state.sconn = sconn;
2314 state.encrypted = encrypted;
2315 state.seqnum = seqnum;
2316 state.reqs = NULL;
2317 state.num_reqs = 0;
2319 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
2320 TALLOC_FREE(state.reqs);
2321 return false;
2323 for (i=0; i<state.num_reqs; i++) {
2324 state.reqs[i]->chain = state.reqs;
2326 *reqs = state.reqs;
2327 *num_reqs = state.num_reqs;
2328 return true;
2331 /****************************************************************************
2332 Check if services need reloading.
2333 ****************************************************************************/
2335 static void check_reload(struct smbd_server_connection *sconn, time_t t)
2338 if (last_smb_conf_reload_time == 0) {
2339 last_smb_conf_reload_time = t;
2342 if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
2343 reload_services(sconn, conn_snum_used, true);
2344 last_smb_conf_reload_time = t;
2348 static bool fd_is_readable(int fd)
2350 int ret, revents;
2352 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2354 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2358 static void smbd_server_connection_write_handler(
2359 struct smbd_server_connection *sconn)
2361 /* TODO: make write nonblocking */
2364 static void smbd_server_connection_read_handler(
2365 struct smbd_server_connection *sconn, int fd)
2367 uint8_t *inbuf = NULL;
2368 size_t inbuf_len = 0;
2369 size_t unread_bytes = 0;
2370 bool encrypted = false;
2371 TALLOC_CTX *mem_ctx = talloc_tos();
2372 NTSTATUS status;
2373 uint32_t seqnum;
2375 bool from_client;
2377 if (lp_async_smb_echo_handler()
2378 && fd_is_readable(sconn->smb1.echo_handler.trusted_fd)) {
2380 * This is the super-ugly hack to prefer the packets
2381 * forwarded by the echo handler over the ones by the
2382 * client directly
2384 fd = sconn->smb1.echo_handler.trusted_fd;
2387 from_client = (sconn->sock == fd);
2389 if (from_client) {
2390 smbd_lock_socket(sconn);
2392 if (!fd_is_readable(fd)) {
2393 DEBUG(10,("the echo listener was faster\n"));
2394 smbd_unlock_socket(sconn);
2395 return;
2399 /* TODO: make this completely nonblocking */
2400 status = receive_smb_talloc(mem_ctx, sconn, fd,
2401 (char **)(void *)&inbuf,
2402 0, /* timeout */
2403 &unread_bytes,
2404 &encrypted,
2405 &inbuf_len, &seqnum,
2406 false /* trusted channel */);
2408 if (from_client) {
2409 smbd_unlock_socket(sconn);
2412 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2413 goto process;
2415 if (NT_STATUS_IS_ERR(status)) {
2416 exit_server_cleanly("failed to receive smb request");
2418 if (!NT_STATUS_IS_OK(status)) {
2419 return;
2422 process:
2423 process_smb(sconn, inbuf, inbuf_len, unread_bytes,
2424 seqnum, encrypted, NULL);
2427 static void smbd_server_connection_handler(struct event_context *ev,
2428 struct fd_event *fde,
2429 uint16_t flags,
2430 void *private_data)
2432 struct smbd_server_connection *conn = talloc_get_type(private_data,
2433 struct smbd_server_connection);
2435 if (flags & EVENT_FD_WRITE) {
2436 smbd_server_connection_write_handler(conn);
2437 return;
2439 if (flags & EVENT_FD_READ) {
2440 smbd_server_connection_read_handler(conn, conn->sock);
2441 return;
2445 static void smbd_server_echo_handler(struct event_context *ev,
2446 struct fd_event *fde,
2447 uint16_t flags,
2448 void *private_data)
2450 struct smbd_server_connection *conn = talloc_get_type(private_data,
2451 struct smbd_server_connection);
2453 if (flags & EVENT_FD_WRITE) {
2454 smbd_server_connection_write_handler(conn);
2455 return;
2457 if (flags & EVENT_FD_READ) {
2458 smbd_server_connection_read_handler(
2459 conn, conn->smb1.echo_handler.trusted_fd);
2460 return;
2464 #ifdef CLUSTER_SUPPORT
2466 struct smbd_release_ip_state {
2467 struct smbd_server_connection *sconn;
2468 char addr[INET6_ADDRSTRLEN];
2471 /****************************************************************************
2472 received when we should release a specific IP
2473 ****************************************************************************/
2474 static void release_ip(const char *ip, void *priv)
2476 struct smbd_release_ip_state *state =
2477 talloc_get_type_abort(priv,
2478 struct smbd_release_ip_state);
2479 const char *addr = state->addr;
2480 const char *p = addr;
2482 if (strncmp("::ffff:", addr, 7) == 0) {
2483 p = addr + 7;
2486 DEBUG(10, ("Got release IP message for %s, "
2487 "our address is %s\n", ip, p));
2489 if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
2490 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
2491 ip));
2493 * With SMB2 we should do a clean disconnect,
2494 * the previous_session_id in the session setup
2495 * will cleanup the old session, tcons and opens.
2497 * A clean disconnect is needed in order to support
2498 * durable handles.
2500 * Note: typically this is never triggered
2501 * as we got a TCP RST (triggered by ctdb event scripts)
2502 * before we get CTDB_SRVID_RELEASE_IP.
2504 * We used to call _exit(1) here, but as this was mostly never
2505 * triggered and has implication on our process model,
2506 * we can just use smbd_server_connection_terminate()
2507 * (also for SMB1).
2509 smbd_server_connection_terminate(state->sconn,
2510 "CTDB_SRVID_RELEASE_IP");
2511 return;
2515 static NTSTATUS smbd_register_ips(struct smbd_server_connection *sconn,
2516 struct sockaddr_storage *srv,
2517 struct sockaddr_storage *clnt)
2519 struct smbd_release_ip_state *state;
2520 struct ctdbd_connection *cconn;
2522 cconn = messaging_ctdbd_connection();
2523 if (cconn == NULL) {
2524 return NT_STATUS_NO_MEMORY;
2527 state = talloc_zero(sconn, struct smbd_release_ip_state);
2528 if (state == NULL) {
2529 return NT_STATUS_NO_MEMORY;
2531 state->sconn = sconn;
2532 if (print_sockaddr(state->addr, sizeof(state->addr), srv) == NULL) {
2533 return NT_STATUS_NO_MEMORY;
2536 return ctdbd_register_ips(cconn, srv, clnt, release_ip, state);
2539 static int client_get_tcp_info(int sock, struct sockaddr_storage *server,
2540 struct sockaddr_storage *client)
2542 socklen_t length;
2543 length = sizeof(*server);
2544 if (getsockname(sock, (struct sockaddr *)server, &length) != 0) {
2545 return -1;
2547 length = sizeof(*client);
2548 if (getpeername(sock, (struct sockaddr *)client, &length) != 0) {
2549 return -1;
2551 return 0;
2553 #endif
2556 * Send keepalive packets to our client
2558 static bool keepalive_fn(const struct timeval *now, void *private_data)
2560 struct smbd_server_connection *sconn = talloc_get_type_abort(
2561 private_data, struct smbd_server_connection);
2562 bool ret;
2564 if (sconn->using_smb2) {
2565 /* Don't do keepalives on an SMB2 connection. */
2566 return false;
2569 smbd_lock_socket(sconn);
2570 ret = send_keepalive(sconn->sock);
2571 smbd_unlock_socket(sconn);
2573 if (!ret) {
2574 char addr[INET6_ADDRSTRLEN];
2576 * Try and give an error message saying what
2577 * client failed.
2579 DEBUG(0, ("send_keepalive failed for client %s. "
2580 "Error %s - exiting\n",
2581 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2582 strerror(errno)));
2583 return False;
2585 return True;
2589 * Do the recurring check if we're idle
2591 static bool deadtime_fn(const struct timeval *now, void *private_data)
2593 struct smbd_server_connection *sconn =
2594 (struct smbd_server_connection *)private_data;
2596 if ((conn_num_open(sconn) == 0)
2597 || (conn_idle_all(sconn, now->tv_sec))) {
2598 DEBUG( 2, ( "Closing idle connection\n" ) );
2599 messaging_send(sconn->msg_ctx,
2600 messaging_server_id(sconn->msg_ctx),
2601 MSG_SHUTDOWN, &data_blob_null);
2602 return False;
2605 return True;
2609 * Do the recurring log file and smb.conf reload checks.
2612 static bool housekeeping_fn(const struct timeval *now, void *private_data)
2614 struct smbd_server_connection *sconn = talloc_get_type_abort(
2615 private_data, struct smbd_server_connection);
2617 DEBUG(5, ("housekeeping\n"));
2619 change_to_root_user();
2621 /* update printer queue caches if necessary */
2622 update_monitored_printq_cache(sconn->msg_ctx);
2624 /* check if we need to reload services */
2625 check_reload(sconn, time_mono(NULL));
2628 * Force a log file check.
2630 force_check_log_size();
2631 check_log_size();
2632 return true;
2636 * Read an smb packet in the echo handler child, giving the parent
2637 * smbd one second to react once the socket becomes readable.
2640 struct smbd_echo_read_state {
2641 struct tevent_context *ev;
2642 struct smbd_server_connection *sconn;
2644 char *buf;
2645 size_t buflen;
2646 uint32_t seqnum;
2649 static void smbd_echo_read_readable(struct tevent_req *subreq);
2650 static void smbd_echo_read_waited(struct tevent_req *subreq);
2652 static struct tevent_req *smbd_echo_read_send(
2653 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2654 struct smbd_server_connection *sconn)
2656 struct tevent_req *req, *subreq;
2657 struct smbd_echo_read_state *state;
2659 req = tevent_req_create(mem_ctx, &state,
2660 struct smbd_echo_read_state);
2661 if (req == NULL) {
2662 return NULL;
2664 state->ev = ev;
2665 state->sconn = sconn;
2667 subreq = wait_for_read_send(state, ev, sconn->sock);
2668 if (tevent_req_nomem(subreq, req)) {
2669 return tevent_req_post(req, ev);
2671 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2672 return req;
2675 static void smbd_echo_read_readable(struct tevent_req *subreq)
2677 struct tevent_req *req = tevent_req_callback_data(
2678 subreq, struct tevent_req);
2679 struct smbd_echo_read_state *state = tevent_req_data(
2680 req, struct smbd_echo_read_state);
2681 bool ok;
2682 int err;
2684 ok = wait_for_read_recv(subreq, &err);
2685 TALLOC_FREE(subreq);
2686 if (!ok) {
2687 tevent_req_nterror(req, map_nt_error_from_unix(err));
2688 return;
2692 * Give the parent smbd one second to step in
2695 subreq = tevent_wakeup_send(
2696 state, state->ev, timeval_current_ofs(1, 0));
2697 if (tevent_req_nomem(subreq, req)) {
2698 return;
2700 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2703 static void smbd_echo_read_waited(struct tevent_req *subreq)
2705 struct tevent_req *req = tevent_req_callback_data(
2706 subreq, struct tevent_req);
2707 struct smbd_echo_read_state *state = tevent_req_data(
2708 req, struct smbd_echo_read_state);
2709 struct smbd_server_connection *sconn = state->sconn;
2710 bool ok;
2711 NTSTATUS status;
2712 size_t unread = 0;
2713 bool encrypted;
2715 ok = tevent_wakeup_recv(subreq);
2716 TALLOC_FREE(subreq);
2717 if (!ok) {
2718 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2719 return;
2722 ok = smbd_lock_socket_internal(sconn);
2723 if (!ok) {
2724 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2725 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2726 return;
2729 if (!fd_is_readable(sconn->sock)) {
2730 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2731 (int)getpid()));
2733 ok = smbd_unlock_socket_internal(sconn);
2734 if (!ok) {
2735 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2736 DEBUG(1, ("%s: failed to unlock socket\n",
2737 __location__));
2738 return;
2741 subreq = wait_for_read_send(state, state->ev, sconn->sock);
2742 if (tevent_req_nomem(subreq, req)) {
2743 return;
2745 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2746 return;
2749 status = receive_smb_talloc(state, sconn, sconn->sock, &state->buf,
2750 0 /* timeout */,
2751 &unread,
2752 &encrypted,
2753 &state->buflen,
2754 &state->seqnum,
2755 false /* trusted_channel*/);
2757 if (tevent_req_nterror(req, status)) {
2758 tevent_req_nterror(req, status);
2759 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2760 (int)getpid(), nt_errstr(status)));
2761 return;
2764 ok = smbd_unlock_socket_internal(sconn);
2765 if (!ok) {
2766 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2767 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2768 return;
2770 tevent_req_done(req);
2773 static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2774 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2776 struct smbd_echo_read_state *state = tevent_req_data(
2777 req, struct smbd_echo_read_state);
2778 NTSTATUS status;
2780 if (tevent_req_is_nterror(req, &status)) {
2781 return status;
2783 *pbuf = talloc_move(mem_ctx, &state->buf);
2784 *pbuflen = state->buflen;
2785 *pseqnum = state->seqnum;
2786 return NT_STATUS_OK;
2789 struct smbd_echo_state {
2790 struct tevent_context *ev;
2791 struct iovec *pending;
2792 struct smbd_server_connection *sconn;
2793 int parent_pipe;
2795 struct tevent_fd *parent_fde;
2797 struct tevent_req *write_req;
2800 static void smbd_echo_writer_done(struct tevent_req *req);
2802 static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2804 int num_pending;
2806 if (state->write_req != NULL) {
2807 return;
2810 num_pending = talloc_array_length(state->pending);
2811 if (num_pending == 0) {
2812 return;
2815 state->write_req = writev_send(state, state->ev, NULL,
2816 state->parent_pipe, false,
2817 state->pending, num_pending);
2818 if (state->write_req == NULL) {
2819 DEBUG(1, ("writev_send failed\n"));
2820 exit(1);
2823 talloc_steal(state->write_req, state->pending);
2824 state->pending = NULL;
2826 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2827 state);
2830 static void smbd_echo_writer_done(struct tevent_req *req)
2832 struct smbd_echo_state *state = tevent_req_callback_data(
2833 req, struct smbd_echo_state);
2834 ssize_t written;
2835 int err;
2837 written = writev_recv(req, &err);
2838 TALLOC_FREE(req);
2839 state->write_req = NULL;
2840 if (written == -1) {
2841 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2842 exit(1);
2844 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2845 smbd_echo_activate_writer(state);
2848 static bool smbd_echo_reply(struct smbd_echo_state *state,
2849 uint8_t *inbuf, size_t inbuf_len,
2850 uint32_t seqnum)
2852 struct smb_request req;
2853 uint16_t num_replies;
2854 char *outbuf;
2855 bool ok;
2857 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2858 DEBUG(10, ("Got netbios keepalive\n"));
2860 * Just swallow it
2862 return true;
2865 if (inbuf_len < smb_size) {
2866 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2867 return false;
2869 if (!valid_smb_header(state->sconn, inbuf)) {
2870 DEBUG(10, ("Got invalid SMB header\n"));
2871 return false;
2874 if (!init_smb_request(&req, state->sconn, inbuf, 0, false,
2875 seqnum)) {
2876 return false;
2878 req.inbuf = inbuf;
2880 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2881 smb_messages[req.cmd].name
2882 ? smb_messages[req.cmd].name : "unknown"));
2884 if (req.cmd != SMBecho) {
2885 return false;
2887 if (req.wct < 1) {
2888 return false;
2891 num_replies = SVAL(req.vwv+0, 0);
2892 if (num_replies != 1) {
2893 /* Not a Windows "Hey, you're still there?" request */
2894 return false;
2897 if (!create_outbuf(talloc_tos(), &req, (const char *)req.inbuf, &outbuf,
2898 1, req.buflen)) {
2899 DEBUG(10, ("create_outbuf failed\n"));
2900 return false;
2902 req.outbuf = (uint8_t *)outbuf;
2904 SSVAL(req.outbuf, smb_vwv0, num_replies);
2906 if (req.buflen > 0) {
2907 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2910 ok = srv_send_smb(req.sconn,
2911 (char *)outbuf,
2912 true, seqnum+1,
2913 false, &req.pcd);
2914 TALLOC_FREE(outbuf);
2915 if (!ok) {
2916 exit(1);
2919 return true;
2922 static void smbd_echo_exit(struct tevent_context *ev,
2923 struct tevent_fd *fde, uint16_t flags,
2924 void *private_data)
2926 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2927 exit(0);
2930 static void smbd_echo_got_packet(struct tevent_req *req);
2932 static void smbd_echo_loop(struct smbd_server_connection *sconn,
2933 int parent_pipe)
2935 struct smbd_echo_state *state;
2936 struct tevent_req *read_req;
2938 state = talloc_zero(sconn, struct smbd_echo_state);
2939 if (state == NULL) {
2940 DEBUG(1, ("talloc failed\n"));
2941 return;
2943 state->sconn = sconn;
2944 state->parent_pipe = parent_pipe;
2945 state->ev = s3_tevent_context_init(state);
2946 if (state->ev == NULL) {
2947 DEBUG(1, ("tevent_context_init failed\n"));
2948 TALLOC_FREE(state);
2949 return;
2951 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2952 TEVENT_FD_READ, smbd_echo_exit,
2953 state);
2954 if (state->parent_fde == NULL) {
2955 DEBUG(1, ("tevent_add_fd failed\n"));
2956 TALLOC_FREE(state);
2957 return;
2960 read_req = smbd_echo_read_send(state, state->ev, sconn);
2961 if (read_req == NULL) {
2962 DEBUG(1, ("smbd_echo_read_send failed\n"));
2963 TALLOC_FREE(state);
2964 return;
2966 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2968 while (true) {
2969 if (tevent_loop_once(state->ev) == -1) {
2970 DEBUG(1, ("tevent_loop_once failed: %s\n",
2971 strerror(errno)));
2972 break;
2975 TALLOC_FREE(state);
2978 static void smbd_echo_got_packet(struct tevent_req *req)
2980 struct smbd_echo_state *state = tevent_req_callback_data(
2981 req, struct smbd_echo_state);
2982 NTSTATUS status;
2983 char *buf = NULL;
2984 size_t buflen = 0;
2985 uint32_t seqnum = 0;
2986 bool reply;
2988 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2989 TALLOC_FREE(req);
2990 if (!NT_STATUS_IS_OK(status)) {
2991 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2992 nt_errstr(status)));
2993 exit(1);
2996 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2997 if (!reply) {
2998 size_t num_pending;
2999 struct iovec *tmp;
3000 struct iovec *iov;
3002 num_pending = talloc_array_length(state->pending);
3003 tmp = talloc_realloc(state, state->pending, struct iovec,
3004 num_pending+1);
3005 if (tmp == NULL) {
3006 DEBUG(1, ("talloc_realloc failed\n"));
3007 exit(1);
3009 state->pending = tmp;
3011 if (buflen >= smb_size) {
3013 * place the seqnum in the packet so that the main process
3014 * can reply with signing
3016 SIVAL(buf, smb_ss_field, seqnum);
3017 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
3020 iov = &state->pending[num_pending];
3021 iov->iov_base = buf;
3022 iov->iov_len = buflen;
3024 DEBUG(10,("echo_handler[%d]: forward to main\n",
3025 (int)getpid()));
3026 smbd_echo_activate_writer(state);
3029 req = smbd_echo_read_send(state, state->ev, state->sconn);
3030 if (req == NULL) {
3031 DEBUG(1, ("smbd_echo_read_send failed\n"));
3032 exit(1);
3034 tevent_req_set_callback(req, smbd_echo_got_packet, state);
3039 * Handle SMBecho requests in a forked child process
3041 bool fork_echo_handler(struct smbd_server_connection *sconn)
3043 int listener_pipe[2];
3044 int res;
3045 pid_t child;
3047 res = pipe(listener_pipe);
3048 if (res == -1) {
3049 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
3050 return false;
3052 sconn->smb1.echo_handler.socket_lock_fd = create_unlink_tmp(lp_lockdir());
3053 if (sconn->smb1.echo_handler.socket_lock_fd == -1) {
3054 DEBUG(1, ("Could not create lock fd: %s\n", strerror(errno)));
3055 goto fail;
3058 child = fork();
3059 if (child == 0) {
3060 NTSTATUS status;
3062 close(listener_pipe[0]);
3063 set_blocking(listener_pipe[1], false);
3065 status = reinit_after_fork(sconn->msg_ctx,
3066 sconn->ev_ctx,
3067 false);
3068 if (!NT_STATUS_IS_OK(status)) {
3069 DEBUG(1, ("reinit_after_fork failed: %s\n",
3070 nt_errstr(status)));
3071 exit(1);
3073 smbd_echo_loop(sconn, listener_pipe[1]);
3074 exit(0);
3076 close(listener_pipe[1]);
3077 listener_pipe[1] = -1;
3078 sconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
3080 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), child));
3083 * Without smb signing this is the same as the normal smbd
3084 * listener. This needs to change once signing comes in.
3086 sconn->smb1.echo_handler.trusted_fde = tevent_add_fd(sconn->ev_ctx,
3087 sconn,
3088 sconn->smb1.echo_handler.trusted_fd,
3089 TEVENT_FD_READ,
3090 smbd_server_echo_handler,
3091 sconn);
3092 if (sconn->smb1.echo_handler.trusted_fde == NULL) {
3093 DEBUG(1, ("event_add_fd failed\n"));
3094 goto fail;
3097 return true;
3099 fail:
3100 if (listener_pipe[0] != -1) {
3101 close(listener_pipe[0]);
3103 if (listener_pipe[1] != -1) {
3104 close(listener_pipe[1]);
3106 sconn->smb1.echo_handler.trusted_fd = -1;
3107 if (sconn->smb1.echo_handler.socket_lock_fd != -1) {
3108 close(sconn->smb1.echo_handler.socket_lock_fd);
3110 sconn->smb1.echo_handler.trusted_fd = -1;
3111 sconn->smb1.echo_handler.socket_lock_fd = -1;
3112 return false;
3115 static bool uid_in_use(const struct user_struct *user, uid_t uid)
3117 while (user) {
3118 if (user->session_info &&
3119 (user->session_info->unix_token->uid == uid)) {
3120 return true;
3122 user = user->next;
3124 return false;
3127 static bool gid_in_use(const struct user_struct *user, gid_t gid)
3129 while (user) {
3130 if (user->session_info != NULL) {
3131 int i;
3132 struct security_unix_token *utok;
3134 utok = user->session_info->unix_token;
3135 if (utok->gid == gid) {
3136 return true;
3138 for(i=0; i<utok->ngroups; i++) {
3139 if (utok->groups[i] == gid) {
3140 return true;
3144 user = user->next;
3146 return false;
3149 static bool sid_in_use(const struct user_struct *user,
3150 const struct dom_sid *psid)
3152 while (user) {
3153 struct security_token *tok;
3155 if (user->session_info == NULL) {
3156 continue;
3158 tok = user->session_info->security_token;
3159 if (tok == NULL) {
3161 * Not sure session_info->security_token can
3162 * ever be NULL. This check might be not
3163 * necessary.
3165 continue;
3167 if (security_token_has_sid(tok, psid)) {
3168 return true;
3170 user = user->next;
3172 return false;
3175 static bool id_in_use(const struct user_struct *user,
3176 const struct id_cache_ref *id)
3178 switch(id->type) {
3179 case UID:
3180 return uid_in_use(user, id->id.uid);
3181 case GID:
3182 return gid_in_use(user, id->id.gid);
3183 case SID:
3184 return sid_in_use(user, &id->id.sid);
3185 default:
3186 break;
3188 return false;
3191 static void smbd_id_cache_kill(struct messaging_context *msg_ctx,
3192 void *private_data,
3193 uint32_t msg_type,
3194 struct server_id server_id,
3195 DATA_BLOB* data)
3197 const char *msg = (data && data->data)
3198 ? (const char *)data->data : "<NULL>";
3199 struct id_cache_ref id;
3200 struct smbd_server_connection *sconn =
3201 talloc_get_type_abort(private_data,
3202 struct smbd_server_connection);
3204 if (!id_cache_ref_parse(msg, &id)) {
3205 DEBUG(0, ("Invalid ?ID: %s\n", msg));
3206 return;
3209 if (id_in_use(sconn->users, &id)) {
3210 exit_server_cleanly(msg);
3212 id_cache_delete_from_cache(&id);
3215 NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn,
3216 enum protocol_types protocol)
3218 NTSTATUS status;
3220 set_Protocol(protocol);
3221 conn->protocol = protocol;
3223 if (protocol >= PROTOCOL_SMB2_02) {
3224 status = smb2srv_session_table_init(conn);
3225 if (!NT_STATUS_IS_OK(status)) {
3226 return status;
3229 status = smb2srv_open_table_init(conn);
3230 if (!NT_STATUS_IS_OK(status)) {
3231 return status;
3233 } else {
3234 status = smb1srv_session_table_init(conn);
3235 if (!NT_STATUS_IS_OK(status)) {
3236 return status;
3239 status = smb1srv_tcon_table_init(conn);
3240 if (!NT_STATUS_IS_OK(status)) {
3241 return status;
3244 status = smb1srv_open_table_init(conn);
3245 if (!NT_STATUS_IS_OK(status)) {
3246 return status;
3250 return NT_STATUS_OK;
3253 static void smbd_tevent_trace_callback(enum tevent_trace_point point,
3254 void *private_data)
3256 struct smbXsrv_connection *conn =
3257 talloc_get_type_abort(private_data,
3258 struct smbXsrv_connection);
3260 switch (point) {
3261 case TEVENT_TRACE_BEFORE_WAIT:
3263 * This just removes compiler warning
3264 * without profile support
3266 conn->smbd_idle_profstamp = 0;
3267 START_PROFILE_STAMP(smbd_idle, conn->smbd_idle_profstamp);
3268 break;
3269 case TEVENT_TRACE_AFTER_WAIT:
3270 END_PROFILE_STAMP(smbd_idle, conn->smbd_idle_profstamp);
3271 break;
3275 /****************************************************************************
3276 Process commands from the client
3277 ****************************************************************************/
3279 void smbd_process(struct tevent_context *ev_ctx,
3280 struct messaging_context *msg_ctx,
3281 int sock_fd,
3282 bool interactive)
3284 TALLOC_CTX *frame = talloc_stackframe();
3285 struct smbXsrv_connection *conn;
3286 struct smbd_server_connection *sconn;
3287 struct sockaddr_storage ss;
3288 struct sockaddr *sa = NULL;
3289 socklen_t sa_socklen;
3290 struct tsocket_address *local_address = NULL;
3291 struct tsocket_address *remote_address = NULL;
3292 const char *locaddr = NULL;
3293 const char *remaddr = NULL;
3294 char *rhost;
3295 int ret;
3297 conn = talloc_zero(ev_ctx, struct smbXsrv_connection);
3298 if (conn == NULL) {
3299 DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n"));
3300 exit_server_cleanly("talloc_zero(struct smbXsrv_connection).\n");
3303 conn->ev_ctx = ev_ctx;
3304 conn->msg_ctx = msg_ctx;
3306 sconn = talloc_zero(conn, struct smbd_server_connection);
3307 if (!sconn) {
3308 exit_server("failed to create smbd_server_connection");
3311 conn->sconn = sconn;
3312 sconn->conn = conn;
3315 * TODO: remove this...:-)
3317 global_smbXsrv_connection = conn;
3319 sconn->ev_ctx = ev_ctx;
3320 sconn->msg_ctx = msg_ctx;
3321 sconn->sock = sock_fd;
3322 sconn->smb1.echo_handler.trusted_fd = -1;
3323 sconn->smb1.echo_handler.socket_lock_fd = -1;
3325 if (!interactive) {
3326 smbd_setup_sig_term_handler(sconn);
3327 smbd_setup_sig_hup_handler(sconn);
3329 if (!serverid_register(messaging_server_id(msg_ctx),
3330 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
3331 |FLAG_MSG_DBWRAP
3332 |FLAG_MSG_PRINT_GENERAL)) {
3333 exit_server_cleanly("Could not register myself in "
3334 "serverid.tdb");
3338 if (lp_srv_maxprotocol() >= PROTOCOL_SMB2_02) {
3340 * We're not making the decision here,
3341 * we're just allowing the client
3342 * to decide between SMB1 and SMB2
3343 * with the first negprot
3344 * packet.
3346 sconn->using_smb2 = true;
3349 /* Ensure child is set to blocking mode */
3350 set_blocking(sconn->sock,True);
3352 set_socket_options(sconn->sock, "SO_KEEPALIVE");
3353 set_socket_options(sconn->sock, lp_socket_options());
3355 sa = (struct sockaddr *)(void *)&ss;
3356 sa_socklen = sizeof(ss);
3357 ret = getpeername(sconn->sock, sa, &sa_socklen);
3358 if (ret != 0) {
3359 int level = (errno == ENOTCONN)?2:0;
3360 DEBUG(level,("getpeername() failed - %s\n", strerror(errno)));
3361 exit_server_cleanly("getpeername() failed.\n");
3363 ret = tsocket_address_bsd_from_sockaddr(sconn,
3364 sa, sa_socklen,
3365 &remote_address);
3366 if (ret != 0) {
3367 DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
3368 __location__, strerror(errno)));
3369 exit_server_cleanly("tsocket_address_bsd_from_sockaddr remote failed.\n");
3372 sa = (struct sockaddr *)(void *)&ss;
3373 sa_socklen = sizeof(ss);
3374 ret = getsockname(sconn->sock, sa, &sa_socklen);
3375 if (ret != 0) {
3376 int level = (errno == ENOTCONN)?2:0;
3377 DEBUG(level,("getsockname() failed - %s\n", strerror(errno)));
3378 exit_server_cleanly("getsockname() failed.\n");
3380 ret = tsocket_address_bsd_from_sockaddr(sconn,
3381 sa, sa_socklen,
3382 &local_address);
3383 if (ret != 0) {
3384 DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
3385 __location__, strerror(errno)));
3386 exit_server_cleanly("tsocket_address_bsd_from_sockaddr remote failed.\n");
3389 sconn->local_address = local_address;
3390 sconn->remote_address = remote_address;
3392 if (tsocket_address_is_inet(local_address, "ip")) {
3393 locaddr = tsocket_address_inet_addr_string(
3394 sconn->local_address,
3395 talloc_tos());
3396 if (locaddr == NULL) {
3397 DEBUG(0,("%s: tsocket_address_inet_addr_string local failed - %s\n",
3398 __location__, strerror(errno)));
3399 exit_server_cleanly("tsocket_address_inet_addr_string local failed.\n");
3401 } else {
3402 locaddr = "0.0.0.0";
3405 if (tsocket_address_is_inet(remote_address, "ip")) {
3406 remaddr = tsocket_address_inet_addr_string(
3407 sconn->remote_address,
3408 talloc_tos());
3409 if (remaddr == NULL) {
3410 DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
3411 __location__, strerror(errno)));
3412 exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n");
3414 } else {
3415 remaddr = "0.0.0.0";
3418 /* this is needed so that we get decent entries
3419 in smbstatus for port 445 connects */
3420 set_remote_machine_name(remaddr, false);
3421 reload_services(sconn, conn_snum_used, true);
3424 * Before the first packet, check the global hosts allow/ hosts deny
3425 * parameters before doing any parsing of packets passed to us by the
3426 * client. This prevents attacks on our parsing code from hosts not in
3427 * the hosts allow list.
3430 ret = get_remote_hostname(remote_address,
3431 &rhost,
3432 talloc_tos());
3433 if (ret < 0) {
3434 DEBUG(0,("%s: get_remote_hostname failed - %s\n",
3435 __location__, strerror(errno)));
3436 exit_server_cleanly("get_remote_hostname failed.\n");
3438 if (strequal(rhost, "UNKNOWN")) {
3439 rhost = talloc_strdup(talloc_tos(), remaddr);
3441 sconn->remote_hostname = talloc_move(sconn, &rhost);
3443 sub_set_socket_ids(remaddr,
3444 sconn->remote_hostname,
3445 locaddr);
3447 if (!allow_access(lp_hostsdeny(-1), lp_hostsallow(-1),
3448 sconn->remote_hostname,
3449 remaddr)) {
3451 * send a negative session response "not listening on calling
3452 * name"
3454 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
3455 DEBUG( 1, ("Connection denied from %s to %s\n",
3456 tsocket_address_string(remote_address, talloc_tos()),
3457 tsocket_address_string(local_address, talloc_tos())));
3458 (void)srv_send_smb(sconn,(char *)buf, false,
3459 0, false, NULL);
3460 exit_server_cleanly("connection denied");
3463 DEBUG(10, ("Connection allowed from %s to %s\n",
3464 tsocket_address_string(remote_address, talloc_tos()),
3465 tsocket_address_string(local_address, talloc_tos())));
3467 if (lp_preload_modules()) {
3468 smb_load_modules(lp_preload_modules());
3471 smb_perfcount_init();
3473 if (!init_account_policy()) {
3474 exit_server("Could not open account policy tdb.\n");
3477 if (*lp_rootdir(talloc_tos())) {
3478 if (chroot(lp_rootdir(talloc_tos())) != 0) {
3479 DEBUG(0,("Failed to change root to %s\n",
3480 lp_rootdir(talloc_tos())));
3481 exit_server("Failed to chroot()");
3483 if (chdir("/") == -1) {
3484 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir(talloc_tos())));
3485 exit_server("Failed to chroot()");
3487 DEBUG(0,("Changed root to %s\n", lp_rootdir(talloc_tos())));
3490 if (!srv_init_signing(sconn)) {
3491 exit_server("Failed to init smb_signing");
3494 if (!file_init(sconn)) {
3495 exit_server("file_init() failed");
3498 /* Setup oplocks */
3499 if (!init_oplocks(sconn))
3500 exit_server("Failed to init oplocks");
3502 /* register our message handlers */
3503 messaging_register(sconn->msg_ctx, sconn,
3504 MSG_SMB_FORCE_TDIS, msg_force_tdis);
3505 messaging_register(sconn->msg_ctx, sconn,
3506 MSG_SMB_CLOSE_FILE, msg_close_file);
3507 messaging_register(sconn->msg_ctx, sconn,
3508 MSG_SMB_FILE_RENAME, msg_file_was_renamed);
3510 id_cache_register_msgs(sconn->msg_ctx);
3511 messaging_deregister(sconn->msg_ctx, ID_CACHE_KILL, NULL);
3512 messaging_register(sconn->msg_ctx, sconn,
3513 ID_CACHE_KILL, smbd_id_cache_kill);
3515 messaging_deregister(sconn->msg_ctx,
3516 MSG_SMB_CONF_UPDATED, sconn->ev_ctx);
3517 messaging_register(sconn->msg_ctx, sconn,
3518 MSG_SMB_CONF_UPDATED, smbd_conf_updated);
3521 * Use the default MSG_DEBUG handler to avoid rebroadcasting
3522 * MSGs to all child processes
3524 messaging_deregister(sconn->msg_ctx,
3525 MSG_DEBUG, NULL);
3526 messaging_register(sconn->msg_ctx, NULL,
3527 MSG_DEBUG, debug_message);
3529 if ((lp_keepalive() != 0)
3530 && !(event_add_idle(ev_ctx, NULL,
3531 timeval_set(lp_keepalive(), 0),
3532 "keepalive", keepalive_fn,
3533 sconn))) {
3534 DEBUG(0, ("Could not add keepalive event\n"));
3535 exit(1);
3538 if (!(event_add_idle(ev_ctx, NULL,
3539 timeval_set(IDLE_CLOSED_TIMEOUT, 0),
3540 "deadtime", deadtime_fn, sconn))) {
3541 DEBUG(0, ("Could not add deadtime event\n"));
3542 exit(1);
3545 if (!(event_add_idle(ev_ctx, NULL,
3546 timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
3547 "housekeeping", housekeeping_fn, sconn))) {
3548 DEBUG(0, ("Could not add housekeeping event\n"));
3549 exit(1);
3552 #ifdef CLUSTER_SUPPORT
3554 if (lp_clustering()) {
3556 * We need to tell ctdb about our client's TCP
3557 * connection, so that for failover ctdbd can send
3558 * tickle acks, triggering a reconnection by the
3559 * client.
3562 struct sockaddr_storage srv, clnt;
3564 if (client_get_tcp_info(sconn->sock, &srv, &clnt) == 0) {
3565 NTSTATUS status;
3566 status = smbd_register_ips(sconn, &srv, &clnt);
3567 if (!NT_STATUS_IS_OK(status)) {
3568 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
3569 nt_errstr(status)));
3571 } else
3573 DEBUG(0,("Unable to get tcp info for "
3574 "CTDB_CONTROL_TCP_CLIENT: %s\n",
3575 strerror(errno)));
3579 #endif
3581 sconn->nbt.got_session = false;
3583 sconn->smb1.negprot.max_recv = MIN(lp_max_xmit(),BUFFER_SIZE);
3585 sconn->smb1.sessions.done_sesssetup = false;
3586 sconn->smb1.sessions.max_send = BUFFER_SIZE;
3587 sconn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
3589 if (!init_dptrs(sconn)) {
3590 exit_server("init_dptrs() failed");
3593 sconn->smb1.fde = event_add_fd(ev_ctx,
3594 sconn,
3595 sconn->sock,
3596 EVENT_FD_READ,
3597 smbd_server_connection_handler,
3598 sconn);
3599 if (!sconn->smb1.fde) {
3600 exit_server("failed to create smbd_server_connection fde");
3603 sconn->conn->local_address = sconn->local_address;
3604 sconn->conn->remote_address = sconn->remote_address;
3605 sconn->conn->remote_hostname = sconn->remote_hostname;
3606 sconn->conn->protocol = PROTOCOL_NONE;
3608 TALLOC_FREE(frame);
3610 tevent_set_trace_callback(ev_ctx, smbd_tevent_trace_callback, conn);
3612 while (True) {
3613 frame = talloc_stackframe_pool(8192);
3615 errno = 0;
3616 if (tevent_loop_once(ev_ctx) == -1) {
3617 if (errno != EINTR) {
3618 DEBUG(3, ("tevent_loop_once failed: %s,"
3619 " exiting\n", strerror(errno) ));
3620 break;
3624 TALLOC_FREE(frame);
3627 exit_server_cleanly(NULL);
3630 bool req_is_in_chain(struct smb_request *req)
3632 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
3634 * We're right now handling a subsequent request, so we must
3635 * be in a chain
3637 return true;
3640 if (!is_andx_req(req->cmd)) {
3641 return false;
3644 if (req->wct < 2) {
3646 * Okay, an illegal request, but definitely not chained :-)
3648 return false;
3651 return (CVAL(req->vwv+0, 0) != 0xFF);