LCOV - code coverage report
Current view: top level - source3/smbd - smb1_process.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 242 977 24.8 %
Date: 2024-06-13 04:01:37 Functions: 22 49 44.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    process incoming packets - main loop
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Volker Lendecke 2005-2007
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "../lib/tsocket/tsocket.h"
      23             : #include "system/filesys.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "smbd/smbXsrv_open.h"
      27             : #include "librpc/gen_ndr/netlogon.h"
      28             : #include "../lib/async_req/async_sock.h"
      29             : #include "ctdbd_conn.h"
      30             : #include "../lib/util/select.h"
      31             : #include "printing/queue_process.h"
      32             : #include "system/select.h"
      33             : #include "passdb.h"
      34             : #include "auth.h"
      35             : #include "messages.h"
      36             : #include "lib/messages_ctdb.h"
      37             : #include "smbprofile.h"
      38             : #include "rpc_server/spoolss/srv_spoolss_nt.h"
      39             : #include "../lib/util/tevent_ntstatus.h"
      40             : #include "../libcli/security/dom_sid.h"
      41             : #include "../libcli/security/security_token.h"
      42             : #include "lib/id_cache.h"
      43             : #include "lib/util/sys_rw_data.h"
      44             : #include "system/threads.h"
      45             : #include "lib/pthreadpool/pthreadpool_tevent.h"
      46             : #include "util_event.h"
      47             : #include "libcli/smb/smbXcli_base.h"
      48             : #include "lib/util/time_basic.h"
      49             : #include "source3/lib/substitute.h"
      50             : 
      51             : /* Internal message queue for deferred opens. */
      52             : struct pending_message_list {
      53             :         struct pending_message_list *next, *prev;
      54             :         struct timeval request_time; /* When was this first issued? */
      55             :         struct smbd_server_connection *sconn;
      56             :         struct smbXsrv_connection *xconn;
      57             :         struct tevent_timer *te;
      58             :         struct smb_perfcount_data pcd;
      59             :         uint32_t seqnum;
      60             :         bool encrypted;
      61             :         bool processed;
      62             :         DATA_BLOB buf;
      63             :         struct deferred_open_record *open_rec;
      64             : };
      65             : 
      66             : static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf);
      67             : 
      68        5320 : void smbd_echo_init(struct smbXsrv_connection *xconn)
      69             : {
      70        5320 :         xconn->smb1.echo_handler.trusted_fd = -1;
      71        5320 :         xconn->smb1.echo_handler.socket_lock_fd = -1;
      72             : #ifdef HAVE_ROBUST_MUTEXES
      73        5320 :         xconn->smb1.echo_handler.socket_mutex = NULL;
      74             : #endif
      75        5320 : }
      76             : 
      77        1464 : static bool smbd_echo_active(struct smbXsrv_connection *xconn)
      78             : {
      79        1464 :         if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
      80           0 :                 return true;
      81             :         }
      82             : 
      83             : #ifdef HAVE_ROBUST_MUTEXES
      84        1464 :         if (xconn->smb1.echo_handler.socket_mutex != NULL) {
      85           0 :                 return true;
      86             :         }
      87             : #endif
      88             : 
      89        1464 :         return false;
      90             : }
      91             : 
      92         732 : static bool smbd_lock_socket_internal(struct smbXsrv_connection *xconn)
      93             : {
      94         732 :         if (!smbd_echo_active(xconn)) {
      95         732 :                 return true;
      96             :         }
      97             : 
      98           0 :         xconn->smb1.echo_handler.ref_count++;
      99             : 
     100           0 :         if (xconn->smb1.echo_handler.ref_count > 1) {
     101           0 :                 return true;
     102             :         }
     103             : 
     104           0 :         DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
     105             : 
     106             : #ifdef HAVE_ROBUST_MUTEXES
     107           0 :         if (xconn->smb1.echo_handler.socket_mutex != NULL) {
     108           0 :                 int ret = EINTR;
     109             : 
     110           0 :                 while (ret == EINTR) {
     111           0 :                         ret = pthread_mutex_lock(
     112             :                                 xconn->smb1.echo_handler.socket_mutex);
     113           0 :                         if (ret == 0) {
     114           0 :                                 break;
     115             :                         }
     116             :                 }
     117           0 :                 if (ret != 0) {
     118           0 :                         DEBUG(1, ("pthread_mutex_lock failed: %s\n",
     119             :                                   strerror(ret)));
     120           0 :                         return false;
     121             :                 }
     122             :         }
     123             : #endif
     124             : 
     125           0 :         if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
     126             :                 bool ok;
     127             : 
     128             :                 do {
     129           0 :                         ok = fcntl_lock(
     130             :                                 xconn->smb1.echo_handler.socket_lock_fd,
     131             :                                 F_SETLKW, 0, 0, F_WRLCK);
     132           0 :                 } while (!ok && (errno == EINTR));
     133             : 
     134           0 :                 if (!ok) {
     135           0 :                         DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
     136           0 :                         return false;
     137             :                 }
     138             :         }
     139             : 
     140           0 :         DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
     141             : 
     142           0 :         return true;
     143             : }
     144             : 
     145         732 : void smbd_lock_socket(struct smbXsrv_connection *xconn)
     146             : {
     147         732 :         if (!smbd_lock_socket_internal(xconn)) {
     148           0 :                 exit_server_cleanly("failed to lock socket");
     149             :         }
     150         732 : }
     151             : 
     152         732 : static bool smbd_unlock_socket_internal(struct smbXsrv_connection *xconn)
     153             : {
     154         732 :         if (!smbd_echo_active(xconn)) {
     155         732 :                 return true;
     156             :         }
     157             : 
     158           0 :         xconn->smb1.echo_handler.ref_count--;
     159             : 
     160           0 :         if (xconn->smb1.echo_handler.ref_count > 0) {
     161           0 :                 return true;
     162             :         }
     163             : 
     164             : #ifdef HAVE_ROBUST_MUTEXES
     165           0 :         if (xconn->smb1.echo_handler.socket_mutex != NULL) {
     166             :                 int ret;
     167           0 :                 ret = pthread_mutex_unlock(
     168             :                         xconn->smb1.echo_handler.socket_mutex);
     169           0 :                 if (ret != 0) {
     170           0 :                         DEBUG(1, ("pthread_mutex_unlock failed: %s\n",
     171             :                                   strerror(ret)));
     172           0 :                         return false;
     173             :                 }
     174             :         }
     175             : #endif
     176             : 
     177           0 :         if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
     178             :                 bool ok;
     179             : 
     180             :                 do {
     181           0 :                         ok = fcntl_lock(
     182             :                                 xconn->smb1.echo_handler.socket_lock_fd,
     183             :                                 F_SETLKW, 0, 0, F_UNLCK);
     184           0 :                 } while (!ok && (errno == EINTR));
     185             : 
     186           0 :                 if (!ok) {
     187           0 :                         DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
     188           0 :                         return false;
     189             :                 }
     190             :         }
     191             : 
     192           0 :         DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
     193             : 
     194           0 :         return true;
     195             : }
     196             : 
     197         732 : void smbd_unlock_socket(struct smbXsrv_connection *xconn)
     198             : {
     199         732 :         if (!smbd_unlock_socket_internal(xconn)) {
     200           0 :                 exit_server_cleanly("failed to unlock socket");
     201             :         }
     202         732 : }
     203             : 
     204             : /* Accessor function for smb_read_error for smbd functions. */
     205             : 
     206             : /****************************************************************************
     207             :  Send an smb to a fd.
     208             : ****************************************************************************/
     209             : 
     210         732 : bool smb1_srv_send(struct smbXsrv_connection *xconn, char *buffer,
     211             :                    bool do_signing, uint32_t seqnum,
     212             :                    bool do_encrypt,
     213             :                    struct smb_perfcount_data *pcd)
     214             : {
     215         732 :         size_t len = 0;
     216             :         ssize_t ret;
     217         732 :         char *buf_out = buffer;
     218             : 
     219         732 :         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
     220             :                 /*
     221             :                  * we're not supposed to do any io
     222             :                  */
     223           0 :                 return true;
     224             :         }
     225             : 
     226         732 :         smbd_lock_socket(xconn);
     227             : 
     228         732 :         if (do_signing) {
     229             :                 NTSTATUS status;
     230             : 
     231             :                 /* Sign the outgoing packet if required. */
     232         152 :                 status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
     233         152 :                 if (!NT_STATUS_IS_OK(status)) {
     234           0 :                         DBG_ERR("Failed to calculate signing mac: %s\n",
     235             :                                 nt_errstr(status));
     236           0 :                         return false;
     237             :                 }
     238             :         }
     239             : 
     240         732 :         if (do_encrypt) {
     241           0 :                 char *enc = NULL;
     242           0 :                 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &enc);
     243           0 :                 if (!NT_STATUS_IS_OK(status)) {
     244           0 :                         DEBUG(0, ("send_smb: SMB encryption failed "
     245             :                                 "on outgoing packet! Error %s\n",
     246             :                                 nt_errstr(status) ));
     247           0 :                         SAFE_FREE(enc);
     248           0 :                         ret = -1;
     249           0 :                         goto out;
     250             :                 }
     251           0 :                 buf_out = enc;
     252             :         }
     253             : 
     254         732 :         len = smb_len_large(buf_out) + 4;
     255             : 
     256         732 :         ret = write_data(xconn->transport.sock, buf_out, len);
     257         732 :         if (ret <= 0) {
     258          13 :                 int saved_errno = errno;
     259             :                 /*
     260             :                  * Try and give an error message saying what
     261             :                  * client failed.
     262             :                  */
     263          13 :                 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
     264             :                          (int)getpid(), (int)len,
     265             :                          smbXsrv_connection_dbg(xconn),
     266             :                          (int)ret, strerror(saved_errno)));
     267          13 :                 errno = saved_errno;
     268             : 
     269          13 :                 srv_free_enc_buffer(xconn, buf_out);
     270          13 :                 goto out;
     271             :         }
     272             : 
     273         719 :         SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
     274         719 :         srv_free_enc_buffer(xconn, buf_out);
     275         732 : out:
     276         732 :         SMB_PERFCOUNT_END(pcd);
     277             : 
     278         732 :         smbd_unlock_socket(xconn);
     279         732 :         return (ret > 0);
     280             : }
     281             : 
     282             : /* Socket functions for smbd packet processing. */
     283             : 
     284         229 : static bool valid_packet_size(size_t len)
     285             : {
     286             :         /*
     287             :          * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
     288             :          * of header. Don't print the error if this fits.... JRA.
     289             :          */
     290             : 
     291         229 :         if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
     292           0 :                 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
     293             :                                         (unsigned long)len));
     294           0 :                 return false;
     295             :         }
     296         229 :         return true;
     297             : }
     298             : 
     299             : /****************************************************************************
     300             :  Attempt a zerocopy writeX read. We know here that len > smb_size-4
     301             : ****************************************************************************/
     302             : 
     303             : /*
     304             :  * Unfortunately, earlier versions of smbclient/libsmbclient
     305             :  * don't send this "standard" writeX header. I've fixed this
     306             :  * for 3.2 but we'll use the old method with earlier versions.
     307             :  * Windows and CIFSFS at least use this standard size. Not
     308             :  * sure about MacOSX.
     309             :  */
     310             : 
     311             : #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
     312             :                                 (2*14) + /* word count (including bcc) */ \
     313             :                                 1 /* pad byte */)
     314             : 
     315           0 : static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
     316             :                                                     const char lenbuf[4],
     317             :                                                     struct smbXsrv_connection *xconn,
     318             :                                                     int sock,
     319             :                                                     char **buffer,
     320             :                                                     unsigned int timeout,
     321             :                                                     size_t *p_unread,
     322             :                                                     size_t *len_ret)
     323             : {
     324             :         /* Size of a WRITEX call (+4 byte len). */
     325             :         char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
     326           0 :         ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
     327             :         ssize_t toread;
     328             :         NTSTATUS status;
     329             : 
     330           0 :         memcpy(writeX_header, lenbuf, 4);
     331             : 
     332           0 :         status = read_fd_with_timeout(
     333             :                 sock, writeX_header + 4,
     334             :                 STANDARD_WRITE_AND_X_HEADER_SIZE,
     335             :                 STANDARD_WRITE_AND_X_HEADER_SIZE,
     336             :                 timeout, NULL);
     337             : 
     338           0 :         if (!NT_STATUS_IS_OK(status)) {
     339           0 :                 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
     340             :                           "error = %s.\n",
     341             :                           smbXsrv_connection_dbg(xconn),
     342             :                           nt_errstr(status)));
     343           0 :                 return status;
     344             :         }
     345             : 
     346             :         /*
     347             :          * Ok - now try and see if this is a possible
     348             :          * valid writeX call.
     349             :          */
     350             : 
     351           0 :         if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
     352             :                 /*
     353             :                  * If the data offset is beyond what
     354             :                  * we've read, drain the extra bytes.
     355             :                  */
     356           0 :                 uint16_t doff = SVAL(writeX_header,smb_vwv11);
     357             :                 ssize_t newlen;
     358             : 
     359           0 :                 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
     360           0 :                         size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
     361           0 :                         if (drain_socket(sock, drain) != drain) {
     362           0 :                                 smb_panic("receive_smb_raw_talloc_partial_read:"
     363             :                                         " failed to drain pending bytes");
     364             :                         }
     365             :                 } else {
     366           0 :                         doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
     367             :                 }
     368             : 
     369             :                 /* Spoof down the length and null out the bcc. */
     370           0 :                 set_message_bcc(writeX_header, 0);
     371           0 :                 newlen = smb_len(writeX_header);
     372             : 
     373             :                 /* Copy the header we've written. */
     374             : 
     375           0 :                 *buffer = (char *)talloc_memdup(mem_ctx,
     376             :                                 writeX_header,
     377             :                                 sizeof(writeX_header));
     378             : 
     379           0 :                 if (*buffer == NULL) {
     380           0 :                         DEBUG(0, ("Could not allocate inbuf of length %d\n",
     381             :                                   (int)sizeof(writeX_header)));
     382           0 :                         return NT_STATUS_NO_MEMORY;
     383             :                 }
     384             : 
     385             :                 /* Work out the remaining bytes. */
     386           0 :                 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
     387           0 :                 *len_ret = newlen + 4;
     388           0 :                 return NT_STATUS_OK;
     389             :         }
     390             : 
     391           0 :         if (!valid_packet_size(len)) {
     392           0 :                 return NT_STATUS_INVALID_PARAMETER;
     393             :         }
     394             : 
     395             :         /*
     396             :          * Not a valid writeX call. Just do the standard
     397             :          * talloc and return.
     398             :          */
     399             : 
     400           0 :         *buffer = talloc_array(mem_ctx, char, len+4);
     401             : 
     402           0 :         if (*buffer == NULL) {
     403           0 :                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
     404             :                           (int)len+4));
     405           0 :                 return NT_STATUS_NO_MEMORY;
     406             :         }
     407             : 
     408             :         /* Copy in what we already read. */
     409           0 :         memcpy(*buffer,
     410             :                 writeX_header,
     411             :                 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
     412           0 :         toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
     413             : 
     414           0 :         if(toread > 0) {
     415           0 :                 status = read_packet_remainder(
     416             :                         sock,
     417           0 :                         (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
     418             :                         timeout, toread);
     419             : 
     420           0 :                 if (!NT_STATUS_IS_OK(status)) {
     421           0 :                         DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
     422             :                                    nt_errstr(status)));
     423           0 :                         return status;
     424             :                 }
     425             :         }
     426             : 
     427           0 :         *len_ret = len + 4;
     428           0 :         return NT_STATUS_OK;
     429             : }
     430             : 
     431         267 : static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
     432             :                                        struct smbXsrv_connection *xconn,
     433             :                                        int sock,
     434             :                                        char **buffer, unsigned int timeout,
     435             :                                        size_t *p_unread, size_t *plen)
     436             : {
     437             :         char lenbuf[4];
     438             :         size_t len;
     439         267 :         int min_recv_size = lp_min_receive_file_size();
     440             :         NTSTATUS status;
     441             : 
     442         267 :         *p_unread = 0;
     443             : 
     444         267 :         status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
     445             :                                                   &len);
     446         267 :         if (!NT_STATUS_IS_OK(status)) {
     447          38 :                 return status;
     448             :         }
     449             : 
     450         229 :         if (CVAL(lenbuf,0) == 0 && min_recv_size &&
     451           0 :             (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
     452           0 :                 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
     453           0 :             !smb1_srv_is_signing_active(xconn) &&
     454           0 :             xconn->smb1.echo_handler.trusted_fde == NULL) {
     455             : 
     456           0 :                 return receive_smb_raw_talloc_partial_read(
     457             :                         mem_ctx, lenbuf, xconn, sock, buffer, timeout,
     458             :                         p_unread, plen);
     459             :         }
     460             : 
     461         229 :         if (!valid_packet_size(len)) {
     462           0 :                 return NT_STATUS_INVALID_PARAMETER;
     463             :         }
     464             : 
     465             :         /*
     466             :          * The +4 here can't wrap, we've checked the length above already.
     467             :          */
     468             : 
     469         229 :         *buffer = talloc_array(mem_ctx, char, len+4);
     470             : 
     471         229 :         if (*buffer == NULL) {
     472           0 :                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
     473             :                           (int)len+4));
     474           0 :                 return NT_STATUS_NO_MEMORY;
     475             :         }
     476             : 
     477         229 :         memcpy(*buffer, lenbuf, sizeof(lenbuf));
     478             : 
     479         229 :         status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
     480         229 :         if (!NT_STATUS_IS_OK(status)) {
     481           0 :                 return status;
     482             :         }
     483             : 
     484         229 :         *plen = len + 4;
     485         229 :         return NT_STATUS_OK;
     486             : }
     487             : 
     488         267 : NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
     489             :                              struct smbXsrv_connection *xconn,
     490             :                              int sock,
     491             :                              char **buffer, unsigned int timeout,
     492             :                              size_t *p_unread, bool *p_encrypted,
     493             :                              size_t *p_len,
     494             :                              uint32_t *seqnum,
     495             :                              bool trusted_channel)
     496             : {
     497         267 :         size_t len = 0;
     498             :         NTSTATUS status;
     499             : 
     500         267 :         *p_encrypted = false;
     501             : 
     502         267 :         status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
     503             :                                         p_unread, &len);
     504         267 :         if (!NT_STATUS_IS_OK(status)) {
     505          38 :                 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
     506             :                       ("receive_smb_raw_talloc failed for client %s "
     507             :                        "read error = %s.\n",
     508             :                        smbXsrv_connection_dbg(xconn),
     509             :                        nt_errstr(status)) );
     510          38 :                 return status;
     511             :         }
     512             : 
     513         229 :         if (is_encrypted_packet((uint8_t *)*buffer)) {
     514           0 :                 status = srv_decrypt_buffer(xconn, *buffer);
     515           0 :                 if (!NT_STATUS_IS_OK(status)) {
     516           0 :                         DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
     517             :                                 "incoming packet! Error %s\n",
     518             :                                 nt_errstr(status) ));
     519           0 :                         return status;
     520             :                 }
     521           0 :                 *p_encrypted = true;
     522             :         }
     523             : 
     524             :         /* Check the incoming SMB signature. */
     525         229 :         if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
     526           0 :                 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
     527             :                           "incoming packet!\n"));
     528           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     529             :         }
     530             : 
     531         229 :         *p_len = len;
     532         229 :         return NT_STATUS_OK;
     533             : }
     534             : 
     535             : /****************************************************************************
     536             :  Function to push a message onto the tail of a linked list of smb messages ready
     537             :  for processing.
     538             : ****************************************************************************/
     539             : 
     540           0 : static bool push_queued_message(struct smb_request *req,
     541             :                                 struct timeval request_time,
     542             :                                 struct timeval end_time,
     543             :                                 struct deferred_open_record *open_rec)
     544             : {
     545           0 :         int msg_len = smb_len(req->inbuf) + 4;
     546             :         struct pending_message_list *msg;
     547             : 
     548           0 :         msg = talloc_zero(NULL, struct pending_message_list);
     549             : 
     550           0 :         if(msg == NULL) {
     551           0 :                 DEBUG(0,("push_message: malloc fail (1)\n"));
     552           0 :                 return False;
     553             :         }
     554           0 :         msg->sconn = req->sconn;
     555           0 :         msg->xconn = req->xconn;
     556             : 
     557           0 :         msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
     558           0 :         if(msg->buf.data == NULL) {
     559           0 :                 DEBUG(0,("push_message: malloc fail (2)\n"));
     560           0 :                 TALLOC_FREE(msg);
     561           0 :                 return False;
     562             :         }
     563             : 
     564           0 :         msg->request_time = request_time;
     565           0 :         msg->seqnum = req->seqnum;
     566           0 :         msg->encrypted = req->encrypted;
     567           0 :         msg->processed = false;
     568           0 :         SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
     569             : 
     570           0 :         if (open_rec) {
     571           0 :                 msg->open_rec = talloc_move(msg, &open_rec);
     572             :         }
     573             : 
     574             : #if 0
     575             :         msg->te = tevent_add_timer(msg->sconn->ev_ctx,
     576             :                                    msg,
     577             :                                    end_time,
     578             :                                    smbd_deferred_open_timer,
     579             :                                    msg);
     580             :         if (!msg->te) {
     581             :                 DEBUG(0,("push_message: event_add_timed failed\n"));
     582             :                 TALLOC_FREE(msg);
     583             :                 return false;
     584             :         }
     585             : #endif
     586             : 
     587           0 :         DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
     588             : 
     589           0 :         DEBUG(10,("push_message: pushed message length %u on "
     590             :                   "deferred_open_queue\n", (unsigned int)msg_len));
     591             : 
     592           0 :         return True;
     593             : }
     594             : 
     595             : /****************************************************************************
     596             :  Function to push a deferred open smb message onto a linked list of local smb
     597             :  messages ready for processing.
     598             : ****************************************************************************/
     599             : 
     600           0 : bool push_deferred_open_message_smb1(struct smb_request *req,
     601             :                                      struct timeval timeout,
     602             :                                      struct file_id id,
     603             :                                      struct deferred_open_record *open_rec)
     604             : {
     605             :         struct timeval_buf tvbuf;
     606             :         struct timeval end_time;
     607             : 
     608           0 :         if (req->unread_bytes) {
     609           0 :                 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
     610             :                         "unread_bytes = %u\n",
     611             :                         (unsigned int)req->unread_bytes ));
     612           0 :                 smb_panic("push_deferred_open_message_smb: "
     613             :                         "logic error unread_bytes != 0" );
     614             :         }
     615             : 
     616           0 :         end_time = timeval_sum(&req->request_time, &timeout);
     617             : 
     618           0 :         DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
     619             :                   (unsigned int) smb_len(req->inbuf)+4,
     620             :                   req->mid,
     621             :                   timeval_str_buf(&end_time, false, true, &tvbuf));
     622             : 
     623           0 :         return push_queued_message(req, req->request_time, end_time, open_rec);
     624             : }
     625             : 
     626             : /*
     627             :  * Only allow 5 outstanding trans requests. We're allocating memory, so
     628             :  * prevent a DoS.
     629             :  */
     630             : 
     631          12 : NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
     632             : {
     633          12 :         int count = 0;
     634          12 :         for (; list != NULL; list = list->next) {
     635             : 
     636           0 :                 if (list->mid == mid) {
     637           0 :                         return NT_STATUS_INVALID_PARAMETER;
     638             :                 }
     639             : 
     640           0 :                 count += 1;
     641             :         }
     642          12 :         if (count > 5) {
     643           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     644             :         }
     645             : 
     646          12 :         return NT_STATUS_OK;
     647             : }
     648             : 
     649             : /*
     650             : These flags determine some of the permissions required to do an operation 
     651             : 
     652             : Note that I don't set NEED_WRITE on some write operations because they
     653             : are used by some brain-dead clients when printing, and I don't want to
     654             : force write permissions on print services.
     655             : */
     656             : #define AS_USER (1<<0)
     657             : #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
     658             : #define TIME_INIT (1<<2)
     659             : #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
     660             : #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
     661             : #define DO_CHDIR (1<<6)
     662             : 
     663             : /* 
     664             :    define a list of possible SMB messages and their corresponding
     665             :    functions. Any message that has a NULL function is unimplemented -
     666             :    please feel free to contribute implementations!
     667             : */
     668             : static const struct smb_message_struct {
     669             :         const char *name;
     670             :         void (*fn)(struct smb_request *req);
     671             :         int flags;
     672             : } smb_messages[256] = {
     673             : 
     674             : /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
     675             : /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
     676             : /* 0x02 */ { "SMBopen",reply_open,AS_USER },
     677             : /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
     678             : /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
     679             : /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
     680             : /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
     681             : /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
     682             : /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
     683             : /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
     684             : /* 0x0a */ { "SMBread",reply_read,AS_USER},
     685             : /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
     686             : /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
     687             : /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
     688             : /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
     689             : /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
     690             : /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
     691             : /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
     692             : /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
     693             : /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
     694             : /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
     695             : /* 0x15 */ { NULL, NULL, 0 },
     696             : /* 0x16 */ { NULL, NULL, 0 },
     697             : /* 0x17 */ { NULL, NULL, 0 },
     698             : /* 0x18 */ { NULL, NULL, 0 },
     699             : /* 0x19 */ { NULL, NULL, 0 },
     700             : /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
     701             : /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
     702             : /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
     703             : /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
     704             : /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
     705             : /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
     706             : /* 0x20 */ { "SMBwritec", NULL,0},
     707             : /* 0x21 */ { NULL, NULL, 0 },
     708             : /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
     709             : /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
     710             : /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
     711             : /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
     712             : /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
     713             : /* 0x27 */ { "SMBioctl",reply_ioctl,0},
     714             : /* 0x28 */ { "SMBioctls", NULL,AS_USER},
     715             : /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
     716             : /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
     717             : /* 0x2b */ { "SMBecho",reply_echo,0},
     718             : /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
     719             : /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
     720             : /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
     721             : /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
     722             : /* 0x30 */ { NULL, NULL, 0 },
     723             : /* 0x31 */ { NULL, NULL, 0 },
     724             : /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
     725             : /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
     726             : /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
     727             : /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
     728             : /* 0x36 */ { NULL, NULL, 0 },
     729             : /* 0x37 */ { NULL, NULL, 0 },
     730             : /* 0x38 */ { NULL, NULL, 0 },
     731             : /* 0x39 */ { NULL, NULL, 0 },
     732             : /* 0x3a */ { NULL, NULL, 0 },
     733             : /* 0x3b */ { NULL, NULL, 0 },
     734             : /* 0x3c */ { NULL, NULL, 0 },
     735             : /* 0x3d */ { NULL, NULL, 0 },
     736             : /* 0x3e */ { NULL, NULL, 0 },
     737             : /* 0x3f */ { NULL, NULL, 0 },
     738             : /* 0x40 */ { NULL, NULL, 0 },
     739             : /* 0x41 */ { NULL, NULL, 0 },
     740             : /* 0x42 */ { NULL, NULL, 0 },
     741             : /* 0x43 */ { NULL, NULL, 0 },
     742             : /* 0x44 */ { NULL, NULL, 0 },
     743             : /* 0x45 */ { NULL, NULL, 0 },
     744             : /* 0x46 */ { NULL, NULL, 0 },
     745             : /* 0x47 */ { NULL, NULL, 0 },
     746             : /* 0x48 */ { NULL, NULL, 0 },
     747             : /* 0x49 */ { NULL, NULL, 0 },
     748             : /* 0x4a */ { NULL, NULL, 0 },
     749             : /* 0x4b */ { NULL, NULL, 0 },
     750             : /* 0x4c */ { NULL, NULL, 0 },
     751             : /* 0x4d */ { NULL, NULL, 0 },
     752             : /* 0x4e */ { NULL, NULL, 0 },
     753             : /* 0x4f */ { NULL, NULL, 0 },
     754             : /* 0x50 */ { NULL, NULL, 0 },
     755             : /* 0x51 */ { NULL, NULL, 0 },
     756             : /* 0x52 */ { NULL, NULL, 0 },
     757             : /* 0x53 */ { NULL, NULL, 0 },
     758             : /* 0x54 */ { NULL, NULL, 0 },
     759             : /* 0x55 */ { NULL, NULL, 0 },
     760             : /* 0x56 */ { NULL, NULL, 0 },
     761             : /* 0x57 */ { NULL, NULL, 0 },
     762             : /* 0x58 */ { NULL, NULL, 0 },
     763             : /* 0x59 */ { NULL, NULL, 0 },
     764             : /* 0x5a */ { NULL, NULL, 0 },
     765             : /* 0x5b */ { NULL, NULL, 0 },
     766             : /* 0x5c */ { NULL, NULL, 0 },
     767             : /* 0x5d */ { NULL, NULL, 0 },
     768             : /* 0x5e */ { NULL, NULL, 0 },
     769             : /* 0x5f */ { NULL, NULL, 0 },
     770             : /* 0x60 */ { NULL, NULL, 0 },
     771             : /* 0x61 */ { NULL, NULL, 0 },
     772             : /* 0x62 */ { NULL, NULL, 0 },
     773             : /* 0x63 */ { NULL, NULL, 0 },
     774             : /* 0x64 */ { NULL, NULL, 0 },
     775             : /* 0x65 */ { NULL, NULL, 0 },
     776             : /* 0x66 */ { NULL, NULL, 0 },
     777             : /* 0x67 */ { NULL, NULL, 0 },
     778             : /* 0x68 */ { NULL, NULL, 0 },
     779             : /* 0x69 */ { NULL, NULL, 0 },
     780             : /* 0x6a */ { NULL, NULL, 0 },
     781             : /* 0x6b */ { NULL, NULL, 0 },
     782             : /* 0x6c */ { NULL, NULL, 0 },
     783             : /* 0x6d */ { NULL, NULL, 0 },
     784             : /* 0x6e */ { NULL, NULL, 0 },
     785             : /* 0x6f */ { NULL, NULL, 0 },
     786             : /* 0x70 */ { "SMBtcon",reply_tcon,0},
     787             : /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
     788             : /* 0x72 */ { "SMBnegprot",reply_negprot,0},
     789             : /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
     790             : /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
     791             : /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
     792             : /* 0x76 */ { NULL, NULL, 0 },
     793             : /* 0x77 */ { NULL, NULL, 0 },
     794             : /* 0x78 */ { NULL, NULL, 0 },
     795             : /* 0x79 */ { NULL, NULL, 0 },
     796             : /* 0x7a */ { NULL, NULL, 0 },
     797             : /* 0x7b */ { NULL, NULL, 0 },
     798             : /* 0x7c */ { NULL, NULL, 0 },
     799             : /* 0x7d */ { NULL, NULL, 0 },
     800             : /* 0x7e */ { NULL, NULL, 0 },
     801             : /* 0x7f */ { NULL, NULL, 0 },
     802             : /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
     803             : /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
     804             : /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
     805             : /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
     806             : /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
     807             : /* 0x85 */ { NULL, NULL, 0 },
     808             : /* 0x86 */ { NULL, NULL, 0 },
     809             : /* 0x87 */ { NULL, NULL, 0 },
     810             : /* 0x88 */ { NULL, NULL, 0 },
     811             : /* 0x89 */ { NULL, NULL, 0 },
     812             : /* 0x8a */ { NULL, NULL, 0 },
     813             : /* 0x8b */ { NULL, NULL, 0 },
     814             : /* 0x8c */ { NULL, NULL, 0 },
     815             : /* 0x8d */ { NULL, NULL, 0 },
     816             : /* 0x8e */ { NULL, NULL, 0 },
     817             : /* 0x8f */ { NULL, NULL, 0 },
     818             : /* 0x90 */ { NULL, NULL, 0 },
     819             : /* 0x91 */ { NULL, NULL, 0 },
     820             : /* 0x92 */ { NULL, NULL, 0 },
     821             : /* 0x93 */ { NULL, NULL, 0 },
     822             : /* 0x94 */ { NULL, NULL, 0 },
     823             : /* 0x95 */ { NULL, NULL, 0 },
     824             : /* 0x96 */ { NULL, NULL, 0 },
     825             : /* 0x97 */ { NULL, NULL, 0 },
     826             : /* 0x98 */ { NULL, NULL, 0 },
     827             : /* 0x99 */ { NULL, NULL, 0 },
     828             : /* 0x9a */ { NULL, NULL, 0 },
     829             : /* 0x9b */ { NULL, NULL, 0 },
     830             : /* 0x9c */ { NULL, NULL, 0 },
     831             : /* 0x9d */ { NULL, NULL, 0 },
     832             : /* 0x9e */ { NULL, NULL, 0 },
     833             : /* 0x9f */ { NULL, NULL, 0 },
     834             : /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
     835             : /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
     836             : /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
     837             : /* 0xa3 */ { NULL, NULL, 0 },
     838             : /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
     839             : /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
     840             : /* 0xa6 */ { NULL, NULL, 0 },
     841             : /* 0xa7 */ { NULL, NULL, 0 },
     842             : /* 0xa8 */ { NULL, NULL, 0 },
     843             : /* 0xa9 */ { NULL, NULL, 0 },
     844             : /* 0xaa */ { NULL, NULL, 0 },
     845             : /* 0xab */ { NULL, NULL, 0 },
     846             : /* 0xac */ { NULL, NULL, 0 },
     847             : /* 0xad */ { NULL, NULL, 0 },
     848             : /* 0xae */ { NULL, NULL, 0 },
     849             : /* 0xaf */ { NULL, NULL, 0 },
     850             : /* 0xb0 */ { NULL, NULL, 0 },
     851             : /* 0xb1 */ { NULL, NULL, 0 },
     852             : /* 0xb2 */ { NULL, NULL, 0 },
     853             : /* 0xb3 */ { NULL, NULL, 0 },
     854             : /* 0xb4 */ { NULL, NULL, 0 },
     855             : /* 0xb5 */ { NULL, NULL, 0 },
     856             : /* 0xb6 */ { NULL, NULL, 0 },
     857             : /* 0xb7 */ { NULL, NULL, 0 },
     858             : /* 0xb8 */ { NULL, NULL, 0 },
     859             : /* 0xb9 */ { NULL, NULL, 0 },
     860             : /* 0xba */ { NULL, NULL, 0 },
     861             : /* 0xbb */ { NULL, NULL, 0 },
     862             : /* 0xbc */ { NULL, NULL, 0 },
     863             : /* 0xbd */ { NULL, NULL, 0 },
     864             : /* 0xbe */ { NULL, NULL, 0 },
     865             : /* 0xbf */ { NULL, NULL, 0 },
     866             : /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
     867             : /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
     868             : /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
     869             : /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
     870             : /* 0xc4 */ { NULL, NULL, 0 },
     871             : /* 0xc5 */ { NULL, NULL, 0 },
     872             : /* 0xc6 */ { NULL, NULL, 0 },
     873             : /* 0xc7 */ { NULL, NULL, 0 },
     874             : /* 0xc8 */ { NULL, NULL, 0 },
     875             : /* 0xc9 */ { NULL, NULL, 0 },
     876             : /* 0xca */ { NULL, NULL, 0 },
     877             : /* 0xcb */ { NULL, NULL, 0 },
     878             : /* 0xcc */ { NULL, NULL, 0 },
     879             : /* 0xcd */ { NULL, NULL, 0 },
     880             : /* 0xce */ { NULL, NULL, 0 },
     881             : /* 0xcf */ { NULL, NULL, 0 },
     882             : /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
     883             : /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
     884             : /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
     885             : /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
     886             : /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
     887             : /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
     888             : /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
     889             : /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
     890             : /* 0xd8 */ { NULL, NULL, 0 },
     891             : /* 0xd9 */ { NULL, NULL, 0 },
     892             : /* 0xda */ { NULL, NULL, 0 },
     893             : /* 0xdb */ { NULL, NULL, 0 },
     894             : /* 0xdc */ { NULL, NULL, 0 },
     895             : /* 0xdd */ { NULL, NULL, 0 },
     896             : /* 0xde */ { NULL, NULL, 0 },
     897             : /* 0xdf */ { NULL, NULL, 0 },
     898             : /* 0xe0 */ { NULL, NULL, 0 },
     899             : /* 0xe1 */ { NULL, NULL, 0 },
     900             : /* 0xe2 */ { NULL, NULL, 0 },
     901             : /* 0xe3 */ { NULL, NULL, 0 },
     902             : /* 0xe4 */ { NULL, NULL, 0 },
     903             : /* 0xe5 */ { NULL, NULL, 0 },
     904             : /* 0xe6 */ { NULL, NULL, 0 },
     905             : /* 0xe7 */ { NULL, NULL, 0 },
     906             : /* 0xe8 */ { NULL, NULL, 0 },
     907             : /* 0xe9 */ { NULL, NULL, 0 },
     908             : /* 0xea */ { NULL, NULL, 0 },
     909             : /* 0xeb */ { NULL, NULL, 0 },
     910             : /* 0xec */ { NULL, NULL, 0 },
     911             : /* 0xed */ { NULL, NULL, 0 },
     912             : /* 0xee */ { NULL, NULL, 0 },
     913             : /* 0xef */ { NULL, NULL, 0 },
     914             : /* 0xf0 */ { NULL, NULL, 0 },
     915             : /* 0xf1 */ { NULL, NULL, 0 },
     916             : /* 0xf2 */ { NULL, NULL, 0 },
     917             : /* 0xf3 */ { NULL, NULL, 0 },
     918             : /* 0xf4 */ { NULL, NULL, 0 },
     919             : /* 0xf5 */ { NULL, NULL, 0 },
     920             : /* 0xf6 */ { NULL, NULL, 0 },
     921             : /* 0xf7 */ { NULL, NULL, 0 },
     922             : /* 0xf8 */ { NULL, NULL, 0 },
     923             : /* 0xf9 */ { NULL, NULL, 0 },
     924             : /* 0xfa */ { NULL, NULL, 0 },
     925             : /* 0xfb */ { NULL, NULL, 0 },
     926             : /* 0xfc */ { NULL, NULL, 0 },
     927             : /* 0xfd */ { NULL, NULL, 0 },
     928             : /* 0xfe */ { NULL, NULL, 0 },
     929             : /* 0xff */ { NULL, NULL, 0 }
     930             : 
     931             : };
     932             : 
     933             : 
     934             : /*******************************************************************
     935             :  Dump a packet to a file.
     936             : ********************************************************************/
     937             : 
     938         212 : static void smb_dump(const char *name, int type, const char *data)
     939             : {
     940             :         size_t len;
     941             :         int fd, i;
     942         212 :         char *fname = NULL;
     943         212 :         if (DEBUGLEVEL < 50) {
     944         212 :                 return;
     945             :         }
     946             : 
     947           0 :         len = smb_len_tcp(data)+4;
     948           0 :         for (i=1;i<100;i++) {
     949           0 :                 fname = talloc_asprintf(talloc_tos(),
     950             :                                 "/tmp/%s.%d.%s",
     951             :                                 name,
     952             :                                 i,
     953             :                                 type ? "req" : "resp");
     954           0 :                 if (fname == NULL) {
     955           0 :                         return;
     956             :                 }
     957           0 :                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
     958           0 :                 if (fd != -1 || errno != EEXIST) break;
     959           0 :                 TALLOC_FREE(fname);
     960             :         }
     961           0 :         if (fd != -1) {
     962           0 :                 ssize_t ret = write(fd, data, len);
     963           0 :                 if (ret != len)
     964           0 :                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
     965           0 :                 close(fd);
     966           0 :                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
     967             :         }
     968           0 :         TALLOC_FREE(fname);
     969             : }
     970             : 
     971          76 : static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
     972             :                                         struct smb_request *req,
     973             :                                         uint8_t type,
     974             :                                         bool *update_session_globalp,
     975             :                                         bool *update_tcon_globalp)
     976             : {
     977          76 :         connection_struct *conn = req->conn;
     978          76 :         struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
     979          76 :         uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
     980          76 :         uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
     981          76 :         bool update_session = false;
     982          76 :         bool update_tcon = false;
     983             : 
     984          76 :         if (req->encrypted) {
     985           0 :                 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
     986             :         }
     987             : 
     988          76 :         if (smb1_srv_is_signing_active(req->xconn)) {
     989          36 :                 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
     990          40 :         } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
     991             :                 /*
     992             :                  * echo can be unsigned. Sesssion setup except final
     993             :                  * session setup response too
     994             :                  */
     995           8 :                 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
     996             :         }
     997             : 
     998         152 :         update_session |= smbXsrv_set_crypto_flag(
     999          76 :                 &session->global->encryption_flags, encrypt_flag);
    1000         152 :         update_session |= smbXsrv_set_crypto_flag(
    1001          76 :                 &session->global->signing_flags, sign_flag);
    1002             : 
    1003          76 :         if (tcon) {
    1004          80 :                 update_tcon |= smbXsrv_set_crypto_flag(
    1005          40 :                         &tcon->global->encryption_flags, encrypt_flag);
    1006          69 :                 update_tcon |= smbXsrv_set_crypto_flag(
    1007          40 :                         &tcon->global->signing_flags, sign_flag);
    1008             :         }
    1009             : 
    1010          76 :         if (update_session) {
    1011          36 :                 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
    1012             :         }
    1013             : 
    1014          76 :         *update_session_globalp = update_session;
    1015          76 :         *update_tcon_globalp = update_tcon;
    1016          76 :         return;
    1017             : }
    1018             : 
    1019             : /****************************************************************************
    1020             :  Prepare everything for calling the actual request function, and potentially
    1021             :  call the request function via the "new" interface.
    1022             : 
    1023             :  Return False if the "legacy" function needs to be called, everything is
    1024             :  prepared.
    1025             : 
    1026             :  Return True if we're done.
    1027             : 
    1028             :  I know this API sucks, but it is the one with the least code change I could
    1029             :  find.
    1030             : ****************************************************************************/
    1031             : 
    1032         212 : static connection_struct *switch_message(uint8_t type, struct smb_request *req)
    1033             : {
    1034         163 :         const struct loadparm_substitution *lp_sub =
    1035          49 :                 loadparm_s3_global_substitution();
    1036             :         int flags;
    1037             :         uint64_t session_tag;
    1038         212 :         connection_struct *conn = NULL;
    1039         212 :         struct smbXsrv_connection *xconn = req->xconn;
    1040         212 :         NTTIME now = timeval_to_nttime(&req->request_time);
    1041         212 :         struct smbXsrv_session *session = NULL;
    1042             :         NTSTATUS status;
    1043             : 
    1044         212 :         errno = 0;
    1045             : 
    1046         212 :         if (!xconn->smb1.negprot.done) {
    1047          98 :                 switch (type) {
    1048             :                         /*
    1049             :                          * Without a negprot the request must
    1050             :                          * either be a negprot, or one of the
    1051             :                          * evil old SMB mailslot messaging types.
    1052             :                          */
    1053          98 :                         case SMBnegprot:
    1054             :                         case SMBsendstrt:
    1055             :                         case SMBsendend:
    1056             :                         case SMBsendtxt:
    1057          98 :                                 break;
    1058           0 :                         default:
    1059           0 :                                 exit_server_cleanly("The first request "
    1060             :                                         "should be a negprot");
    1061             :                 }
    1062          84 :         }
    1063             : 
    1064         212 :         if (smb_messages[type].fn == NULL) {
    1065           0 :                 DEBUG(0,("Unknown message type %d!\n",type));
    1066           0 :                 smb_dump("Unknown", 1, (const char *)req->inbuf);
    1067           0 :                 reply_unknown_new(req, type);
    1068           0 :                 return NULL;
    1069             :         }
    1070             : 
    1071         212 :         flags = smb_messages[type].flags;
    1072             : 
    1073             :         /* In share mode security we must ignore the vuid. */
    1074         212 :         session_tag = req->vuid;
    1075         212 :         conn = req->conn;
    1076             : 
    1077         212 :         DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
    1078             :                  (int)getpid(), (unsigned long)conn));
    1079             : 
    1080         212 :         smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
    1081             : 
    1082             :         /* Ensure this value is replaced in the incoming packet. */
    1083         212 :         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
    1084             : 
    1085             :         /*
    1086             :          * Ensure the correct username is in current_user_info.  This is a
    1087             :          * really ugly bugfix for problems with multiple session_setup_and_X's
    1088             :          * being done and allowing %U and %G substitutions to work correctly.
    1089             :          * There is a reason this code is done here, don't move it unless you
    1090             :          * know what you're doing... :-).
    1091             :          * JRA.
    1092             :          */
    1093             : 
    1094             :         /*
    1095             :          * lookup an existing session
    1096             :          *
    1097             :          * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
    1098             :          * here, the main check is still in change_to_user()
    1099             :          */
    1100         212 :         status = smb1srv_session_lookup(xconn,
    1101             :                                         session_tag,
    1102             :                                         now,
    1103             :                                         &session);
    1104         212 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
    1105           0 :                 switch (type) {
    1106           0 :                 case SMBsesssetupX:
    1107           0 :                         status = NT_STATUS_OK;
    1108           0 :                         break;
    1109           0 :                 default:
    1110           0 :                         DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
    1111             :                                  (unsigned long long)session_tag,
    1112             :                                  (unsigned long long)req->mid));
    1113           0 :                         reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
    1114           0 :                         return conn;
    1115             :                 }
    1116         163 :         }
    1117             : 
    1118         268 :         if (session != NULL &&
    1119         128 :             session->global->auth_session_info != NULL &&
    1120          68 :             !(flags & AS_USER))
    1121             :         {
    1122             :                 /*
    1123             :                  * change_to_user() implies set_current_user_info()
    1124             :                  * and chdir_connect_service().
    1125             :                  *
    1126             :                  * So we only call set_current_user_info if
    1127             :                  * we don't have AS_USER specified.
    1128             :                  */
    1129         148 :                 set_current_user_info(
    1130          56 :                         session->global->auth_session_info->unix_info->sanitized_username,
    1131          56 :                         session->global->auth_session_info->unix_info->unix_name,
    1132          56 :                         session->global->auth_session_info->info->domain_name);
    1133             :         }
    1134             : 
    1135             :         /* Does this call need to be run as the connected user? */
    1136         212 :         if (flags & AS_USER) {
    1137             : 
    1138             :                 /* Does this call need a valid tree connection? */
    1139          12 :                 if (!conn) {
    1140             :                         /*
    1141             :                          * Amazingly, the error code depends on the command
    1142             :                          * (from Samba4).
    1143             :                          */
    1144           0 :                         if (type == SMBntcreateX) {
    1145           0 :                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    1146             :                         } else {
    1147           0 :                                 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
    1148             :                         }
    1149           0 :                         return NULL;
    1150             :                 }
    1151             : 
    1152          12 :                 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
    1153             : 
    1154             :                 /*
    1155             :                  * change_to_user() implies set_current_user_info()
    1156             :                  * and chdir_connect_service().
    1157             :                  */
    1158          12 :                 if (!change_to_user_and_service(conn,session_tag)) {
    1159           0 :                         DEBUG(0, ("Error: Could not change to user. Removing "
    1160             :                                 "deferred open, mid=%llu.\n",
    1161             :                                 (unsigned long long)req->mid));
    1162           0 :                         reply_force_doserror(req, ERRSRV, ERRbaduid);
    1163           0 :                         return conn;
    1164             :                 }
    1165             : 
    1166             :                 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
    1167             : 
    1168             :                 /* Does it need write permission? */
    1169          12 :                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
    1170           0 :                         reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
    1171           0 :                         return conn;
    1172             :                 }
    1173             : 
    1174             :                 /* IPC services are limited */
    1175          12 :                 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
    1176           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1177           0 :                         return conn;
    1178             :                 }
    1179         200 :         } else if (flags & AS_GUEST) {
    1180             :                 /*
    1181             :                  * Does this protocol need to be run as guest? (Only archane
    1182             :                  * messenger service requests have this...)
    1183             :                  */
    1184           0 :                 if (!change_to_guest()) {
    1185           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1186           0 :                         return conn;
    1187             :                 }
    1188             :         } else {
    1189             :                 /* This call needs to be run as root */
    1190         200 :                 change_to_root_user();
    1191             :         }
    1192             : 
    1193             :         /* load service specific parameters */
    1194         212 :         if (conn) {
    1195          40 :                 if (req->encrypted) {
    1196           0 :                         conn->encrypted_tid = true;
    1197             :                         /* encrypted required from now on. */
    1198           0 :                         conn->encrypt_level = SMB_SIGNING_REQUIRED;
    1199          40 :                 } else if (ENCRYPTION_REQUIRED(conn)) {
    1200           0 :                         if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
    1201           0 :                                 DEBUG(1,("service[%s] requires encryption"
    1202             :                                         "%s ACCESS_DENIED. mid=%llu\n",
    1203             :                                         lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    1204             :                                         smb_fn_name(type),
    1205             :                                         (unsigned long long)req->mid));
    1206           0 :                                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1207           0 :                                 return conn;
    1208             :                         }
    1209             :                 }
    1210             : 
    1211          40 :                 if (flags & DO_CHDIR) {
    1212             :                         bool ok;
    1213             : 
    1214          28 :                         ok = chdir_current_service(conn);
    1215          28 :                         if (!ok) {
    1216           0 :                                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1217           0 :                                 return conn;
    1218             :                         }
    1219             :                 }
    1220          40 :                 conn->num_smb_operations++;
    1221             :         }
    1222             : 
    1223             :         /*
    1224             :          * Update encryption and signing state tracking flags that are
    1225             :          * used by smbstatus to display signing and encryption status.
    1226             :          */
    1227         212 :         if (session != NULL) {
    1228          76 :                 bool update_session_global = false;
    1229          76 :                 bool update_tcon_global = false;
    1230             : 
    1231          76 :                 req->session = session;
    1232             : 
    1233          76 :                 smb1srv_update_crypto_flags(session, req, type,
    1234             :                                             &update_session_global,
    1235             :                                             &update_tcon_global);
    1236             : 
    1237          76 :                 if (update_session_global) {
    1238          36 :                         status = smbXsrv_session_update(session);
    1239          36 :                         if (!NT_STATUS_IS_OK(status)) {
    1240           0 :                                 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
    1241           0 :                                 return conn;
    1242             :                         }
    1243             :                 }
    1244             : 
    1245          76 :                 if (update_tcon_global) {
    1246          28 :                         status = smbXsrv_tcon_update(req->conn->tcon);
    1247          28 :                         if (!NT_STATUS_IS_OK(status)) {
    1248           0 :                                 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
    1249           0 :                                 return conn;
    1250             :                         }
    1251             :                 }
    1252             :         }
    1253             : 
    1254         212 :         smb_messages[type].fn(req);
    1255         212 :         return req->conn;
    1256             : }
    1257             : 
    1258             : /****************************************************************************
    1259             :  Construct a reply to the incoming packet.
    1260             : ****************************************************************************/
    1261             : 
    1262         212 : void construct_reply(struct smbXsrv_connection *xconn,
    1263             :                      char *inbuf, int size, size_t unread_bytes,
    1264             :                      uint32_t seqnum, bool encrypted,
    1265             :                      struct smb_perfcount_data *deferred_pcd)
    1266             : {
    1267         212 :         struct smbd_server_connection *sconn = xconn->client->sconn;
    1268             :         struct smb_request *req;
    1269             : 
    1270         212 :         if (!(req = talloc(talloc_tos(), struct smb_request))) {
    1271           0 :                 smb_panic("could not allocate smb_request");
    1272             :         }
    1273             : 
    1274         212 :         if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
    1275             :                               encrypted, seqnum)) {
    1276           0 :                 exit_server_cleanly("Invalid SMB request");
    1277             :         }
    1278             : 
    1279         212 :         req->inbuf  = (uint8_t *)talloc_move(req, &inbuf);
    1280             : 
    1281             :         /* we popped this message off the queue - keep original perf data */
    1282         212 :         if (deferred_pcd)
    1283           0 :                 req->pcd = *deferred_pcd;
    1284             :         else {
    1285         212 :                 SMB_PERFCOUNT_START(&req->pcd);
    1286         212 :                 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
    1287         212 :                 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
    1288             :         }
    1289             : 
    1290         212 :         req->conn = switch_message(req->cmd, req);
    1291             : 
    1292         212 :         if (req->outbuf == NULL) {
    1293             :                 /*
    1294             :                  * Request has suspended itself, will come
    1295             :                  * back here.
    1296             :                  */
    1297         100 :                 return;
    1298             :         }
    1299         112 :         if (CVAL(req->outbuf,0) == 0) {
    1300         112 :                 show_msg((char *)req->outbuf);
    1301             :         }
    1302         112 :         smb_request_done(req);
    1303             : }
    1304             : 
    1305           0 : static void construct_reply_chain(struct smbXsrv_connection *xconn,
    1306             :                                   char *inbuf, int size, uint32_t seqnum,
    1307             :                                   bool encrypted,
    1308             :                                   struct smb_perfcount_data *deferred_pcd)
    1309             : {
    1310           0 :         struct smb_request **reqs = NULL;
    1311             :         struct smb_request *req;
    1312             :         unsigned num_reqs;
    1313             :         bool ok;
    1314             : 
    1315           0 :         ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
    1316             :                               seqnum, &reqs, &num_reqs);
    1317           0 :         if (!ok) {
    1318             :                 char errbuf[smb_size];
    1319           0 :                 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
    1320             :                              __LINE__, __FILE__);
    1321           0 :                 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted,
    1322             :                                   NULL)) {
    1323           0 :                         exit_server_cleanly("construct_reply_chain: "
    1324             :                                             "smb1_srv_send failed.");
    1325             :                 }
    1326           0 :                 return;
    1327             :         }
    1328             : 
    1329           0 :         req = reqs[0];
    1330           0 :         req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
    1331             : 
    1332           0 :         req->conn = switch_message(req->cmd, req);
    1333             : 
    1334           0 :         if (req->outbuf == NULL) {
    1335             :                 /*
    1336             :                  * Request has suspended itself, will come
    1337             :                  * back here.
    1338             :                  */
    1339           0 :                 return;
    1340             :         }
    1341           0 :         smb_request_done(req);
    1342             : }
    1343             : 
    1344             : /*
    1345             :  * To be called from an async SMB handler that is potentially chained
    1346             :  * when it is finished for shipping.
    1347             :  */
    1348             : 
    1349         140 : void smb_request_done(struct smb_request *req)
    1350             : {
    1351         140 :         struct smb_request **reqs = NULL;
    1352             :         struct smb_request *first_req;
    1353             :         size_t i, num_reqs, next_index;
    1354             :         NTSTATUS status;
    1355             : 
    1356         140 :         if (req->chain == NULL) {
    1357         140 :                 first_req = req;
    1358         140 :                 goto shipit;
    1359             :         }
    1360             : 
    1361           0 :         reqs = req->chain;
    1362           0 :         num_reqs = talloc_array_length(reqs);
    1363             : 
    1364           0 :         for (i=0; i<num_reqs; i++) {
    1365           0 :                 if (reqs[i] == req) {
    1366           0 :                         break;
    1367             :                 }
    1368             :         }
    1369           0 :         if (i == num_reqs) {
    1370             :                 /*
    1371             :                  * Invalid chain, should not happen
    1372             :                  */
    1373           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    1374           0 :                 goto error;
    1375             :         }
    1376           0 :         next_index = i+1;
    1377             : 
    1378           0 :         while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
    1379           0 :                 struct smb_request *next = reqs[next_index];
    1380             :                 struct smbXsrv_tcon *tcon;
    1381           0 :                 NTTIME now = timeval_to_nttime(&req->request_time);
    1382             : 
    1383           0 :                 next->vuid = SVAL(req->outbuf, smb_uid);
    1384           0 :                 next->tid  = SVAL(req->outbuf, smb_tid);
    1385           0 :                 status = smb1srv_tcon_lookup(req->xconn, next->tid,
    1386             :                                              now, &tcon);
    1387             : 
    1388           0 :                 if (NT_STATUS_IS_OK(status)) {
    1389           0 :                         next->conn = tcon->compat;
    1390             :                 } else {
    1391           0 :                         next->conn = NULL;
    1392             :                 }
    1393           0 :                 next->chain_fsp = req->chain_fsp;
    1394           0 :                 next->inbuf = req->inbuf;
    1395             : 
    1396           0 :                 req = next;
    1397           0 :                 req->conn = switch_message(req->cmd, req);
    1398             : 
    1399           0 :                 if (req->outbuf == NULL) {
    1400             :                         /*
    1401             :                          * Request has suspended itself, will come
    1402             :                          * back here.
    1403             :                          */
    1404           0 :                         return;
    1405             :                 }
    1406           0 :                 next_index += 1;
    1407             :         }
    1408             : 
    1409           0 :         first_req = reqs[0];
    1410             : 
    1411           0 :         for (i=1; i<next_index; i++) {
    1412             :                 bool ok;
    1413             : 
    1414           0 :                 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
    1415           0 :                 if (!ok) {
    1416           0 :                         status = NT_STATUS_INTERNAL_ERROR;
    1417           0 :                         goto error;
    1418             :                 }
    1419             :         }
    1420             : 
    1421           0 :         SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
    1422           0 :         SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
    1423             : 
    1424             :         /*
    1425             :          * This scary statement intends to set the
    1426             :          * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
    1427             :          * to the value last_req->outbuf carries
    1428             :          */
    1429           0 :         SSVAL(first_req->outbuf, smb_flg2,
    1430             :               (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
    1431             :               |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
    1432             : 
    1433             :         /*
    1434             :          * Transfer the error codes from the subrequest to the main one
    1435             :          */
    1436           0 :         SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
    1437           0 :         SSVAL(first_req->outbuf, smb_err,  SVAL(req->outbuf, smb_err));
    1438             : 
    1439           0 :         _smb_setlen_large(
    1440             :                 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
    1441             : 
    1442         140 : shipit:
    1443         458 :         if (!smb1_srv_send(first_req->xconn,
    1444         140 :                           (char *)first_req->outbuf,
    1445         140 :                           true, first_req->seqnum+1,
    1446         140 :                           IS_CONN_ENCRYPTED(req->conn)||first_req->encrypted,
    1447             :                           &first_req->pcd)) {
    1448           0 :                 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
    1449             :                                     "failed.");
    1450             :         }
    1451         140 :         TALLOC_FREE(req);       /* non-chained case */
    1452         140 :         TALLOC_FREE(reqs);      /* chained case */
    1453         140 :         return;
    1454             : 
    1455           0 : error:
    1456             :         {
    1457             :                 char errbuf[smb_size];
    1458           0 :                 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
    1459           0 :                 if (!smb1_srv_send(req->xconn, errbuf, true,
    1460           0 :                                   req->seqnum+1, req->encrypted,
    1461             :                                   NULL)) {
    1462           0 :                         exit_server_cleanly("construct_reply_chain: "
    1463             :                                             "smb1_srv_send failed.");
    1464             :                 }
    1465             :         }
    1466           0 :         TALLOC_FREE(req);       /* non-chained case */
    1467           0 :         TALLOC_FREE(reqs);      /* chained case */
    1468             : }
    1469             : 
    1470             : /****************************************************************************
    1471             :  Process an smb from the client
    1472             : ****************************************************************************/
    1473             : 
    1474         212 : void process_smb1(struct smbXsrv_connection *xconn,
    1475             :                   uint8_t *inbuf, size_t nread, size_t unread_bytes,
    1476             :                   uint32_t seqnum, bool encrypted,
    1477             :                   struct smb_perfcount_data *deferred_pcd)
    1478             : {
    1479         212 :         struct smbd_server_connection *sconn = xconn->client->sconn;
    1480             : 
    1481             :         /* Make sure this is an SMB packet. smb_size contains NetBIOS header
    1482             :          * so subtract 4 from it. */
    1483         212 :         if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
    1484           0 :                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
    1485             :                          smb_len(inbuf)));
    1486             : 
    1487             :                 /* special magic for immediate exit */
    1488           0 :                 if ((nread == 9) &&
    1489           0 :                     (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
    1490           0 :                     lp_parm_bool(-1, "smbd", "suicide mode", false)) {
    1491           0 :                         uint8_t exitcode = CVAL(inbuf, 8);
    1492           0 :                         DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
    1493             :                                     (int)exitcode);
    1494           0 :                         exit(exitcode);
    1495             :                 }
    1496             : 
    1497           0 :                 exit_server_cleanly("Non-SMB packet");
    1498             :         }
    1499             : 
    1500         212 :         show_msg((char *)inbuf);
    1501             : 
    1502         212 :         if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
    1503           0 :                 construct_reply_chain(xconn, (char *)inbuf, nread,
    1504             :                                       seqnum, encrypted, deferred_pcd);
    1505             :         } else {
    1506         212 :                 construct_reply(xconn, (char *)inbuf, nread, unread_bytes,
    1507             :                                 seqnum, encrypted, deferred_pcd);
    1508             :         }
    1509             : 
    1510         212 :         sconn->trans_num++;
    1511         212 : }
    1512             : 
    1513             : /****************************************************************************
    1514             :  Return a string containing the function name of a SMB command.
    1515             : ****************************************************************************/
    1516             : 
    1517         212 : const char *smb_fn_name(int type)
    1518             : {
    1519         212 :         const char *unknown_name = "SMBunknown";
    1520             : 
    1521         212 :         if (smb_messages[type].name == NULL)
    1522           0 :                 return(unknown_name);
    1523             : 
    1524         212 :         return(smb_messages[type].name);
    1525             : }
    1526             : 
    1527             : /****************************************************************************
    1528             :  Helper functions for contruct_reply.
    1529             : ****************************************************************************/
    1530             : 
    1531          38 : void add_to_common_flags2(uint32_t v)
    1532             : {
    1533          38 :         common_flags2 |= v;
    1534          38 : }
    1535             : 
    1536           0 : void remove_from_common_flags2(uint32_t v)
    1537             : {
    1538           0 :         common_flags2 &= ~v;
    1539           0 : }
    1540             : 
    1541             : /**
    1542             :  * @brief Find the smb_cmd offset of the last command pushed
    1543             :  * @param[in] buf       The buffer we're building up
    1544             :  * @retval              Where can we put our next andx cmd?
    1545             :  *
    1546             :  * While chaining requests, the "next" request we're looking at needs to put
    1547             :  * its SMB_Command before the data the previous request already built up added
    1548             :  * to the chain. Find the offset to the place where we have to put our cmd.
    1549             :  */
    1550             : 
    1551           0 : static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
    1552             : {
    1553             :         uint8_t cmd;
    1554             :         size_t ofs;
    1555             : 
    1556           0 :         cmd = CVAL(buf, smb_com);
    1557             : 
    1558           0 :         if (!smb1cli_is_andx_req(cmd)) {
    1559           0 :                 return false;
    1560             :         }
    1561             : 
    1562           0 :         ofs = smb_vwv0;
    1563             : 
    1564           0 :         while (CVAL(buf, ofs) != 0xff) {
    1565             : 
    1566           0 :                 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
    1567           0 :                         return false;
    1568             :                 }
    1569             : 
    1570             :                 /*
    1571             :                  * ofs is from start of smb header, so add the 4 length
    1572             :                  * bytes. The next cmd is right after the wct field.
    1573             :                  */
    1574           0 :                 ofs = SVAL(buf, ofs+2) + 4 + 1;
    1575             : 
    1576           0 :                 if (ofs+4 >= talloc_get_size(buf)) {
    1577           0 :                         return false;
    1578             :                 }
    1579             :         }
    1580             : 
    1581           0 :         *pofs = ofs;
    1582           0 :         return true;
    1583             : }
    1584             : 
    1585             : /**
    1586             :  * @brief Do the smb chaining at a buffer level
    1587             :  * @param[in] poutbuf           Pointer to the talloc'ed buffer to be modified
    1588             :  * @param[in] andx_buf          Buffer to be appended
    1589             :  */
    1590             : 
    1591           0 : static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
    1592             : {
    1593           0 :         uint8_t smb_command     = CVAL(andx_buf, smb_com);
    1594           0 :         uint8_t wct             = CVAL(andx_buf, smb_wct);
    1595           0 :         const uint16_t *vwv     = (const uint16_t *)(andx_buf + smb_vwv);
    1596           0 :         uint32_t num_bytes      = smb_buflen(andx_buf);
    1597           0 :         const uint8_t *bytes    = (const uint8_t *)smb_buf_const(andx_buf);
    1598             : 
    1599             :         uint8_t *outbuf;
    1600             :         size_t old_size, new_size;
    1601             :         size_t ofs;
    1602           0 :         size_t chain_padding = 0;
    1603             :         size_t andx_cmd_ofs;
    1604             : 
    1605             : 
    1606           0 :         old_size = talloc_get_size(*poutbuf);
    1607             : 
    1608           0 :         if ((old_size % 4) != 0) {
    1609             :                 /*
    1610             :                  * Align the wct field of subsequent requests to a 4-byte
    1611             :                  * boundary
    1612             :                  */
    1613           0 :                 chain_padding = 4 - (old_size % 4);
    1614             :         }
    1615             : 
    1616             :         /*
    1617             :          * After the old request comes the new wct field (1 byte), the vwv's
    1618             :          * and the num_bytes field.
    1619             :          */
    1620             : 
    1621           0 :         new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
    1622           0 :         new_size += num_bytes;
    1623             : 
    1624           0 :         if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
    1625           0 :                 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
    1626             :                           (unsigned)new_size));
    1627           0 :                 return false;
    1628             :         }
    1629             : 
    1630           0 :         outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
    1631           0 :         if (outbuf == NULL) {
    1632           0 :                 DEBUG(0, ("talloc failed\n"));
    1633           0 :                 return false;
    1634             :         }
    1635           0 :         *poutbuf = outbuf;
    1636             : 
    1637           0 :         if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
    1638           0 :                 DEBUG(1, ("invalid command chain\n"));
    1639           0 :                 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
    1640           0 :                 return false;
    1641             :         }
    1642             : 
    1643           0 :         if (chain_padding != 0) {
    1644           0 :                 memset(outbuf + old_size, 0, chain_padding);
    1645           0 :                 old_size += chain_padding;
    1646             :         }
    1647             : 
    1648           0 :         SCVAL(outbuf, andx_cmd_ofs, smb_command);
    1649           0 :         SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
    1650             : 
    1651           0 :         ofs = old_size;
    1652             : 
    1653             :         /*
    1654             :          * Push the chained request:
    1655             :          *
    1656             :          * wct field
    1657             :          */
    1658             : 
    1659           0 :         SCVAL(outbuf, ofs, wct);
    1660           0 :         ofs += 1;
    1661             : 
    1662             :         /*
    1663             :          * vwv array
    1664             :          */
    1665             : 
    1666           0 :         memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
    1667             : 
    1668             :         /*
    1669             :          * HACK ALERT
    1670             :          *
    1671             :          * Read&X has an offset into its data buffer at
    1672             :          * vwv[6]. reply_read_andx has no idea anymore that it's
    1673             :          * running from within a chain, so we have to fix up the
    1674             :          * offset here.
    1675             :          *
    1676             :          * Although it looks disgusting at this place, I want to keep
    1677             :          * it here. The alternative would be to push knowledge about
    1678             :          * the andx chain down into read&x again.
    1679             :          */
    1680             : 
    1681           0 :         if (smb_command == SMBreadX) {
    1682             :                 uint8_t *bytes_addr;
    1683             : 
    1684           0 :                 if (wct < 7) {
    1685             :                         /*
    1686             :                          * Invalid read&x response
    1687             :                          */
    1688           0 :                         return false;
    1689             :                 }
    1690             : 
    1691           0 :                 bytes_addr = outbuf + ofs        /* vwv start */
    1692           0 :                         + sizeof(uint16_t) * wct /* vwv array */
    1693             :                         + sizeof(uint16_t)       /* bcc */
    1694           0 :                         + 1;                     /* padding byte */
    1695             : 
    1696           0 :                 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
    1697             :                       bytes_addr - outbuf - 4);
    1698             :         }
    1699             : 
    1700           0 :         ofs += sizeof(uint16_t) * wct;
    1701             : 
    1702             :         /*
    1703             :          * bcc (byte count)
    1704             :          */
    1705             : 
    1706           0 :         SSVAL(outbuf, ofs, num_bytes);
    1707           0 :         ofs += sizeof(uint16_t);
    1708             : 
    1709             :         /*
    1710             :          * The bytes field
    1711             :          */
    1712             : 
    1713           0 :         memcpy(outbuf + ofs, bytes, num_bytes);
    1714             : 
    1715           0 :         return true;
    1716             : }
    1717             : 
    1718         212 : bool smb1_is_chain(const uint8_t *buf)
    1719             : {
    1720             :         uint8_t cmd, wct, andx_cmd;
    1721             : 
    1722         212 :         cmd = CVAL(buf, smb_com);
    1723         212 :         if (!smb1cli_is_andx_req(cmd)) {
    1724         138 :                 return false;
    1725             :         }
    1726          74 :         wct = CVAL(buf, smb_wct);
    1727          74 :         if (wct < 2) {
    1728           0 :                 return false;
    1729             :         }
    1730          74 :         andx_cmd = CVAL(buf, smb_vwv);
    1731          74 :         return (andx_cmd != 0xFF);
    1732             : }
    1733             : 
    1734           0 : bool smb1_walk_chain(const uint8_t *buf,
    1735             :                      bool (*fn)(uint8_t cmd,
    1736             :                                 uint8_t wct, const uint16_t *vwv,
    1737             :                                 uint16_t num_bytes, const uint8_t *bytes,
    1738             :                                 void *private_data),
    1739             :                      void *private_data)
    1740             : {
    1741           0 :         size_t smblen = smb_len(buf);
    1742           0 :         const char *smb_buf = smb_base(buf);
    1743             :         uint8_t cmd, chain_cmd;
    1744             :         uint8_t wct;
    1745             :         const uint16_t *vwv;
    1746             :         uint16_t num_bytes;
    1747             :         const uint8_t *bytes;
    1748             : 
    1749           0 :         cmd = CVAL(buf, smb_com);
    1750           0 :         wct = CVAL(buf, smb_wct);
    1751           0 :         vwv = (const uint16_t *)(buf + smb_vwv);
    1752           0 :         num_bytes = smb_buflen(buf);
    1753           0 :         bytes = (const uint8_t *)smb_buf_const(buf);
    1754             : 
    1755           0 :         if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
    1756           0 :                 return false;
    1757             :         }
    1758             : 
    1759           0 :         if (!smb1cli_is_andx_req(cmd)) {
    1760           0 :                 return true;
    1761             :         }
    1762           0 :         if (wct < 2) {
    1763           0 :                 return false;
    1764             :         }
    1765             : 
    1766           0 :         chain_cmd = CVAL(vwv, 0);
    1767             : 
    1768           0 :         while (chain_cmd != 0xff) {
    1769             :                 uint32_t chain_offset;  /* uint32_t to avoid overflow */
    1770             :                 size_t length_needed;
    1771             :                 ptrdiff_t vwv_offset;
    1772             : 
    1773           0 :                 chain_offset = SVAL(vwv+1, 0);
    1774             : 
    1775             :                 /*
    1776             :                  * Check if the client tries to fool us. The chain
    1777             :                  * offset needs to point beyond the current request in
    1778             :                  * the chain, it needs to strictly grow. Otherwise we
    1779             :                  * might be tricked into an endless loop always
    1780             :                  * processing the same request over and over again. We
    1781             :                  * used to assume that vwv and the byte buffer array
    1782             :                  * in a chain are always attached, but OS/2 the
    1783             :                  * Write&X/Read&X chain puts the Read&X vwv array
    1784             :                  * right behind the Write&X vwv chain. The Write&X bcc
    1785             :                  * array is put behind the Read&X vwv array. So now we
    1786             :                  * check whether the chain offset points strictly
    1787             :                  * behind the previous vwv array. req->buf points
    1788             :                  * right after the vwv array of the previous
    1789             :                  * request. See
    1790             :                  * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
    1791             :                  * more information.
    1792             :                  */
    1793             : 
    1794           0 :                 vwv_offset = ((const char *)vwv - smb_buf);
    1795           0 :                 if (chain_offset <= vwv_offset) {
    1796           0 :                         return false;
    1797             :                 }
    1798             : 
    1799             :                 /*
    1800             :                  * Next check: Make sure the chain offset does not
    1801             :                  * point beyond the overall smb request length.
    1802             :                  */
    1803             : 
    1804           0 :                 length_needed = chain_offset+1; /* wct */
    1805           0 :                 if (length_needed > smblen) {
    1806           0 :                         return false;
    1807             :                 }
    1808             : 
    1809             :                 /*
    1810             :                  * Now comes the pointer magic. Goal here is to set up
    1811             :                  * vwv and buf correctly again. The chain offset (the
    1812             :                  * former vwv[1]) points at the new wct field.
    1813             :                  */
    1814             : 
    1815           0 :                 wct = CVAL(smb_buf, chain_offset);
    1816             : 
    1817           0 :                 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
    1818           0 :                         return false;
    1819             :                 }
    1820             : 
    1821             :                 /*
    1822             :                  * Next consistency check: Make the new vwv array fits
    1823             :                  * in the overall smb request.
    1824             :                  */
    1825             : 
    1826           0 :                 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
    1827           0 :                 if (length_needed > smblen) {
    1828           0 :                         return false;
    1829             :                 }
    1830           0 :                 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
    1831             : 
    1832             :                 /*
    1833             :                  * Now grab the new byte buffer....
    1834             :                  */
    1835             : 
    1836           0 :                 num_bytes = SVAL(vwv+wct, 0);
    1837             : 
    1838             :                 /*
    1839             :                  * .. and check that it fits.
    1840             :                  */
    1841             : 
    1842           0 :                 length_needed += num_bytes;
    1843           0 :                 if (length_needed > smblen) {
    1844           0 :                         return false;
    1845             :                 }
    1846           0 :                 bytes = (const uint8_t *)(vwv+wct+1);
    1847             : 
    1848           0 :                 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
    1849           0 :                         return false;
    1850             :                 }
    1851             : 
    1852           0 :                 if (!smb1cli_is_andx_req(chain_cmd)) {
    1853           0 :                         return true;
    1854             :                 }
    1855           0 :                 chain_cmd = CVAL(vwv, 0);
    1856             :         }
    1857           0 :         return true;
    1858             : }
    1859             : 
    1860           0 : static bool smb1_chain_length_cb(uint8_t cmd,
    1861             :                                  uint8_t wct, const uint16_t *vwv,
    1862             :                                  uint16_t num_bytes, const uint8_t *bytes,
    1863             :                                  void *private_data)
    1864             : {
    1865           0 :         unsigned *count = (unsigned *)private_data;
    1866           0 :         *count += 1;
    1867           0 :         return true;
    1868             : }
    1869             : 
    1870           0 : unsigned smb1_chain_length(const uint8_t *buf)
    1871             : {
    1872           0 :         unsigned count = 0;
    1873             : 
    1874           0 :         if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
    1875           0 :                 return 0;
    1876             :         }
    1877           0 :         return count;
    1878             : }
    1879             : 
    1880             : struct smb1_parse_chain_state {
    1881             :         TALLOC_CTX *mem_ctx;
    1882             :         const uint8_t *buf;
    1883             :         struct smbd_server_connection *sconn;
    1884             :         struct smbXsrv_connection *xconn;
    1885             :         bool encrypted;
    1886             :         uint32_t seqnum;
    1887             : 
    1888             :         struct smb_request **reqs;
    1889             :         unsigned num_reqs;
    1890             : };
    1891             : 
    1892           0 : static bool smb1_parse_chain_cb(uint8_t cmd,
    1893             :                                 uint8_t wct, const uint16_t *vwv,
    1894             :                                 uint16_t num_bytes, const uint8_t *bytes,
    1895             :                                 void *private_data)
    1896             : {
    1897           0 :         struct smb1_parse_chain_state *state =
    1898             :                 (struct smb1_parse_chain_state *)private_data;
    1899             :         struct smb_request **reqs;
    1900             :         struct smb_request *req;
    1901             :         bool ok;
    1902             : 
    1903           0 :         reqs = talloc_realloc(state->mem_ctx, state->reqs,
    1904             :                               struct smb_request *, state->num_reqs+1);
    1905           0 :         if (reqs == NULL) {
    1906           0 :                 return false;
    1907             :         }
    1908           0 :         state->reqs = reqs;
    1909             : 
    1910           0 :         req = talloc(reqs, struct smb_request);
    1911           0 :         if (req == NULL) {
    1912           0 :                 return false;
    1913             :         }
    1914             : 
    1915           0 :         ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
    1916           0 :                               state->encrypted, state->seqnum);
    1917           0 :         if (!ok) {
    1918           0 :                 return false;
    1919             :         }
    1920           0 :         req->cmd = cmd;
    1921           0 :         req->wct = wct;
    1922           0 :         req->vwv = vwv;
    1923           0 :         req->buflen = num_bytes;
    1924           0 :         req->buf = bytes;
    1925             : 
    1926           0 :         reqs[state->num_reqs] = req;
    1927           0 :         state->num_reqs += 1;
    1928           0 :         return true;
    1929             : }
    1930             : 
    1931           0 : bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
    1932             :                       struct smbXsrv_connection *xconn,
    1933             :                       bool encrypted, uint32_t seqnum,
    1934             :                       struct smb_request ***reqs, unsigned *num_reqs)
    1935             : {
    1936           0 :         struct smbd_server_connection *sconn = NULL;
    1937             :         struct smb1_parse_chain_state state;
    1938             :         unsigned i;
    1939             : 
    1940           0 :         if (xconn != NULL) {
    1941           0 :                 sconn = xconn->client->sconn;
    1942             :         }
    1943             : 
    1944           0 :         state.mem_ctx = mem_ctx;
    1945           0 :         state.buf = buf;
    1946           0 :         state.sconn = sconn;
    1947           0 :         state.xconn = xconn;
    1948           0 :         state.encrypted = encrypted;
    1949           0 :         state.seqnum = seqnum;
    1950           0 :         state.reqs = NULL;
    1951           0 :         state.num_reqs = 0;
    1952             : 
    1953           0 :         if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
    1954           0 :                 TALLOC_FREE(state.reqs);
    1955           0 :                 return false;
    1956             :         }
    1957           0 :         for (i=0; i<state.num_reqs; i++) {
    1958           0 :                 state.reqs[i]->chain = state.reqs;
    1959             :         }
    1960           0 :         *reqs = state.reqs;
    1961           0 :         *num_reqs = state.num_reqs;
    1962           0 :         return true;
    1963             : }
    1964             : 
    1965           0 : static bool fd_is_readable(int fd)
    1966             : {
    1967             :         int ret, revents;
    1968             : 
    1969           0 :         ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
    1970             : 
    1971           0 :         return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
    1972             : 
    1973             : }
    1974             : 
    1975           0 : static void smbd_server_connection_write_handler(
    1976             :         struct smbXsrv_connection *xconn)
    1977             : {
    1978             :         /* TODO: make write nonblocking */
    1979           0 : }
    1980             : 
    1981         267 : void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
    1982             :                                               int fd)
    1983             : {
    1984         267 :         uint8_t *inbuf = NULL;
    1985         267 :         size_t inbuf_len = 0;
    1986         267 :         size_t unread_bytes = 0;
    1987         267 :         bool encrypted = false;
    1988         267 :         TALLOC_CTX *mem_ctx = talloc_tos();
    1989             :         NTSTATUS status;
    1990             :         uint32_t seqnum;
    1991             : 
    1992         267 :         bool async_echo = lp_async_smb_echo_handler();
    1993         267 :         bool from_client = false;
    1994             : 
    1995         267 :         if (async_echo) {
    1996           0 :                 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
    1997             :                         /*
    1998             :                          * This is the super-ugly hack to prefer the packets
    1999             :                          * forwarded by the echo handler over the ones by the
    2000             :                          * client directly
    2001             :                          */
    2002           0 :                         fd = xconn->smb1.echo_handler.trusted_fd;
    2003             :                 }
    2004             :         }
    2005             : 
    2006         267 :         from_client = (xconn->transport.sock == fd);
    2007             : 
    2008         267 :         if (async_echo && from_client) {
    2009           0 :                 smbd_lock_socket(xconn);
    2010             : 
    2011           0 :                 if (!fd_is_readable(fd)) {
    2012           0 :                         DEBUG(10,("the echo listener was faster\n"));
    2013           0 :                         smbd_unlock_socket(xconn);
    2014           0 :                         return;
    2015             :                 }
    2016             :         }
    2017             : 
    2018             :         /* TODO: make this completely nonblocking */
    2019         267 :         status = receive_smb_talloc(mem_ctx, xconn, fd,
    2020             :                                     (char **)(void *)&inbuf,
    2021             :                                     0, /* timeout */
    2022             :                                     &unread_bytes,
    2023             :                                     &encrypted,
    2024             :                                     &inbuf_len, &seqnum,
    2025         267 :                                     !from_client /* trusted channel */);
    2026             : 
    2027         267 :         if (async_echo && from_client) {
    2028           0 :                 smbd_unlock_socket(xconn);
    2029             :         }
    2030             : 
    2031         267 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
    2032           0 :                 goto process;
    2033             :         }
    2034         267 :         if (NT_STATUS_IS_ERR(status)) {
    2035          38 :                 exit_server_cleanly("failed to receive smb request");
    2036             :         }
    2037         229 :         if (!NT_STATUS_IS_OK(status)) {
    2038           0 :                 return;
    2039             :         }
    2040             : 
    2041         229 : process:
    2042         229 :         process_smb(xconn, inbuf, inbuf_len, unread_bytes,
    2043             :                     seqnum, encrypted, NULL);
    2044             : }
    2045             : 
    2046           0 : static void smbd_server_echo_handler(struct tevent_context *ev,
    2047             :                                      struct tevent_fd *fde,
    2048             :                                      uint16_t flags,
    2049             :                                      void *private_data)
    2050             : {
    2051           0 :         struct smbXsrv_connection *xconn =
    2052           0 :                 talloc_get_type_abort(private_data,
    2053             :                 struct smbXsrv_connection);
    2054             : 
    2055           0 :         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
    2056             :                 /*
    2057             :                  * we're not supposed to do any io
    2058             :                  */
    2059           0 :                 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
    2060           0 :                 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
    2061           0 :                 return;
    2062             :         }
    2063             : 
    2064           0 :         if (flags & TEVENT_FD_WRITE) {
    2065           0 :                 smbd_server_connection_write_handler(xconn);
    2066           0 :                 return;
    2067             :         }
    2068           0 :         if (flags & TEVENT_FD_READ) {
    2069           0 :                 smbd_smb1_server_connection_read_handler(
    2070             :                         xconn, xconn->smb1.echo_handler.trusted_fd);
    2071           0 :                 return;
    2072             :         }
    2073             : }
    2074             : 
    2075             : /*
    2076             :  * Send keepalive packets to our client
    2077             :  */
    2078          26 : bool keepalive_fn(const struct timeval *now, void *private_data)
    2079             : {
    2080          26 :         struct smbd_server_connection *sconn = talloc_get_type_abort(
    2081             :                 private_data, struct smbd_server_connection);
    2082          26 :         struct smbXsrv_connection *xconn = NULL;
    2083             :         bool ret;
    2084             : 
    2085          26 :         if (sconn->using_smb2) {
    2086             :                 /* Don't do keepalives on an SMB2 connection. */
    2087          26 :                 return false;
    2088             :         }
    2089             : 
    2090             :         /*
    2091             :          * With SMB1 we only have 1 connection
    2092             :          */
    2093           0 :         xconn = sconn->client->connections;
    2094           0 :         smbd_lock_socket(xconn);
    2095           0 :         ret = send_keepalive(xconn->transport.sock);
    2096           0 :         smbd_unlock_socket(xconn);
    2097             : 
    2098           0 :         if (!ret) {
    2099           0 :                 int saved_errno = errno;
    2100             :                 /*
    2101             :                  * Try and give an error message saying what
    2102             :                  * client failed.
    2103             :                  */
    2104           0 :                 DEBUG(0, ("send_keepalive failed for client %s. "
    2105             :                           "Error %s - exiting\n",
    2106             :                           smbXsrv_connection_dbg(xconn),
    2107             :                           strerror(saved_errno)));
    2108           0 :                 errno = saved_errno;
    2109           0 :                 return False;
    2110             :         }
    2111           0 :         return True;
    2112             : }
    2113             : 
    2114             : /*
    2115             :  * Read an smb packet in the echo handler child, giving the parent
    2116             :  * smbd one second to react once the socket becomes readable.
    2117             :  */
    2118             : 
    2119             : struct smbd_echo_read_state {
    2120             :         struct tevent_context *ev;
    2121             :         struct smbXsrv_connection *xconn;
    2122             : 
    2123             :         char *buf;
    2124             :         size_t buflen;
    2125             :         uint32_t seqnum;
    2126             : };
    2127             : 
    2128             : static void smbd_echo_read_readable(struct tevent_req *subreq);
    2129             : static void smbd_echo_read_waited(struct tevent_req *subreq);
    2130             : 
    2131           0 : static struct tevent_req *smbd_echo_read_send(
    2132             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
    2133             :         struct smbXsrv_connection *xconn)
    2134             : {
    2135             :         struct tevent_req *req, *subreq;
    2136             :         struct smbd_echo_read_state *state;
    2137             : 
    2138           0 :         req = tevent_req_create(mem_ctx, &state,
    2139             :                                 struct smbd_echo_read_state);
    2140           0 :         if (req == NULL) {
    2141           0 :                 return NULL;
    2142             :         }
    2143           0 :         state->ev = ev;
    2144           0 :         state->xconn = xconn;
    2145             : 
    2146           0 :         subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
    2147           0 :         if (tevent_req_nomem(subreq, req)) {
    2148           0 :                 return tevent_req_post(req, ev);
    2149             :         }
    2150           0 :         tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
    2151           0 :         return req;
    2152             : }
    2153             : 
    2154           0 : static void smbd_echo_read_readable(struct tevent_req *subreq)
    2155             : {
    2156           0 :         struct tevent_req *req = tevent_req_callback_data(
    2157             :                 subreq, struct tevent_req);
    2158           0 :         struct smbd_echo_read_state *state = tevent_req_data(
    2159             :                 req, struct smbd_echo_read_state);
    2160             :         bool ok;
    2161             :         int err;
    2162             : 
    2163           0 :         ok = wait_for_read_recv(subreq, &err);
    2164           0 :         TALLOC_FREE(subreq);
    2165           0 :         if (!ok) {
    2166           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
    2167           0 :                 return;
    2168             :         }
    2169             : 
    2170             :         /*
    2171             :          * Give the parent smbd one second to step in
    2172             :          */
    2173             : 
    2174           0 :         subreq = tevent_wakeup_send(
    2175             :                 state, state->ev, timeval_current_ofs(1, 0));
    2176           0 :         if (tevent_req_nomem(subreq, req)) {
    2177           0 :                 return;
    2178             :         }
    2179           0 :         tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
    2180             : }
    2181             : 
    2182           0 : static void smbd_echo_read_waited(struct tevent_req *subreq)
    2183             : {
    2184           0 :         struct tevent_req *req = tevent_req_callback_data(
    2185             :                 subreq, struct tevent_req);
    2186           0 :         struct smbd_echo_read_state *state = tevent_req_data(
    2187             :                 req, struct smbd_echo_read_state);
    2188           0 :         struct smbXsrv_connection *xconn = state->xconn;
    2189             :         bool ok;
    2190             :         NTSTATUS status;
    2191           0 :         size_t unread = 0;
    2192             :         bool encrypted;
    2193             : 
    2194           0 :         ok = tevent_wakeup_recv(subreq);
    2195           0 :         TALLOC_FREE(subreq);
    2196           0 :         if (!ok) {
    2197           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
    2198           0 :                 return;
    2199             :         }
    2200             : 
    2201           0 :         ok = smbd_lock_socket_internal(xconn);
    2202           0 :         if (!ok) {
    2203           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(errno));
    2204           0 :                 DEBUG(0, ("%s: failed to lock socket\n", __location__));
    2205           0 :                 return;
    2206             :         }
    2207             : 
    2208           0 :         if (!fd_is_readable(xconn->transport.sock)) {
    2209           0 :                 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
    2210             :                           (int)getpid()));
    2211             : 
    2212           0 :                 ok = smbd_unlock_socket_internal(xconn);
    2213           0 :                 if (!ok) {
    2214           0 :                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
    2215           0 :                         DEBUG(1, ("%s: failed to unlock socket\n",
    2216             :                                 __location__));
    2217           0 :                         return;
    2218             :                 }
    2219             : 
    2220           0 :                 subreq = wait_for_read_send(state, state->ev,
    2221             :                                             xconn->transport.sock, false);
    2222           0 :                 if (tevent_req_nomem(subreq, req)) {
    2223           0 :                         return;
    2224             :                 }
    2225           0 :                 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
    2226           0 :                 return;
    2227             :         }
    2228             : 
    2229           0 :         status = receive_smb_talloc(state, xconn,
    2230             :                                     xconn->transport.sock,
    2231             :                                     &state->buf,
    2232             :                                     0 /* timeout */,
    2233             :                                     &unread,
    2234             :                                     &encrypted,
    2235             :                                     &state->buflen,
    2236             :                                     &state->seqnum,
    2237             :                                     false /* trusted_channel*/);
    2238             : 
    2239           0 :         if (tevent_req_nterror(req, status)) {
    2240           0 :                 tevent_req_nterror(req, status);
    2241           0 :                 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
    2242             :                           (int)getpid(), nt_errstr(status)));
    2243           0 :                 return;
    2244             :         }
    2245             : 
    2246           0 :         ok = smbd_unlock_socket_internal(xconn);
    2247           0 :         if (!ok) {
    2248           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(errno));
    2249           0 :                 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
    2250           0 :                 return;
    2251             :         }
    2252           0 :         tevent_req_done(req);
    2253             : }
    2254             : 
    2255           0 : static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    2256             :                                     char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
    2257             : {
    2258           0 :         struct smbd_echo_read_state *state = tevent_req_data(
    2259             :                 req, struct smbd_echo_read_state);
    2260             :         NTSTATUS status;
    2261             : 
    2262           0 :         if (tevent_req_is_nterror(req, &status)) {
    2263           0 :                 return status;
    2264             :         }
    2265           0 :         *pbuf = talloc_move(mem_ctx, &state->buf);
    2266           0 :         *pbuflen = state->buflen;
    2267           0 :         *pseqnum = state->seqnum;
    2268           0 :         return NT_STATUS_OK;
    2269             : }
    2270             : 
    2271             : struct smbd_echo_state {
    2272             :         struct tevent_context *ev;
    2273             :         struct iovec *pending;
    2274             :         struct smbd_server_connection *sconn;
    2275             :         struct smbXsrv_connection *xconn;
    2276             :         int parent_pipe;
    2277             : 
    2278             :         struct tevent_fd *parent_fde;
    2279             : 
    2280             :         struct tevent_req *write_req;
    2281             : };
    2282             : 
    2283             : static void smbd_echo_writer_done(struct tevent_req *req);
    2284             : 
    2285           0 : static void smbd_echo_activate_writer(struct smbd_echo_state *state)
    2286             : {
    2287             :         int num_pending;
    2288             : 
    2289           0 :         if (state->write_req != NULL) {
    2290           0 :                 return;
    2291             :         }
    2292             : 
    2293           0 :         num_pending = talloc_array_length(state->pending);
    2294           0 :         if (num_pending == 0) {
    2295           0 :                 return;
    2296             :         }
    2297             : 
    2298           0 :         state->write_req = writev_send(state, state->ev, NULL,
    2299             :                                        state->parent_pipe, false,
    2300             :                                        state->pending, num_pending);
    2301           0 :         if (state->write_req == NULL) {
    2302           0 :                 DEBUG(1, ("writev_send failed\n"));
    2303           0 :                 exit(1);
    2304             :         }
    2305             : 
    2306           0 :         talloc_steal(state->write_req, state->pending);
    2307           0 :         state->pending = NULL;
    2308             : 
    2309           0 :         tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
    2310             :                                 state);
    2311             : }
    2312             : 
    2313           0 : static void smbd_echo_writer_done(struct tevent_req *req)
    2314             : {
    2315           0 :         struct smbd_echo_state *state = tevent_req_callback_data(
    2316             :                 req, struct smbd_echo_state);
    2317             :         ssize_t written;
    2318             :         int err;
    2319             : 
    2320           0 :         written = writev_recv(req, &err);
    2321           0 :         TALLOC_FREE(req);
    2322           0 :         state->write_req = NULL;
    2323           0 :         if (written == -1) {
    2324           0 :                 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
    2325           0 :                 exit(1);
    2326             :         }
    2327           0 :         DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
    2328           0 :         smbd_echo_activate_writer(state);
    2329           0 : }
    2330             : 
    2331           0 : static bool smbd_echo_reply(struct smbd_echo_state *state,
    2332             :                             uint8_t *inbuf, size_t inbuf_len,
    2333             :                             uint32_t seqnum)
    2334             : {
    2335             :         struct smb_request req;
    2336             :         uint16_t num_replies;
    2337             :         char *outbuf;
    2338             :         bool ok;
    2339             : 
    2340           0 :         if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
    2341           0 :                 DEBUG(10, ("Got netbios keepalive\n"));
    2342             :                 /*
    2343             :                  * Just swallow it
    2344             :                  */
    2345           0 :                 return true;
    2346             :         }
    2347             : 
    2348           0 :         if (inbuf_len < smb_size) {
    2349           0 :                 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
    2350           0 :                 return false;
    2351             :         }
    2352           0 :         if (!valid_smb1_header(inbuf)) {
    2353           0 :                 DEBUG(10, ("Got invalid SMB header\n"));
    2354           0 :                 return false;
    2355             :         }
    2356             : 
    2357           0 :         if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
    2358             :                               seqnum)) {
    2359           0 :                 return false;
    2360             :         }
    2361           0 :         req.inbuf = inbuf;
    2362             : 
    2363           0 :         DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
    2364             :                    smb_messages[req.cmd].name
    2365             :                    ? smb_messages[req.cmd].name : "unknown"));
    2366             : 
    2367           0 :         if (req.cmd != SMBecho) {
    2368           0 :                 return false;
    2369             :         }
    2370           0 :         if (req.wct < 1) {
    2371           0 :                 return false;
    2372             :         }
    2373             : 
    2374           0 :         num_replies = SVAL(req.vwv+0, 0);
    2375           0 :         if (num_replies != 1) {
    2376             :                 /* Not a Windows "Hey, you're still there?" request */
    2377           0 :                 return false;
    2378             :         }
    2379             : 
    2380           0 :         if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
    2381           0 :                            1, req.buflen)) {
    2382           0 :                 DEBUG(10, ("create_smb1_outbuf failed\n"));
    2383           0 :                 return false;
    2384             :         }
    2385           0 :         req.outbuf = (uint8_t *)outbuf;
    2386             : 
    2387           0 :         SSVAL(req.outbuf, smb_vwv0, num_replies);
    2388             : 
    2389           0 :         if (req.buflen > 0) {
    2390           0 :                 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
    2391             :         }
    2392             : 
    2393           0 :         ok = smb1_srv_send(req.xconn,
    2394             :                           (char *)outbuf,
    2395             :                           true, seqnum+1,
    2396             :                           false, &req.pcd);
    2397           0 :         TALLOC_FREE(outbuf);
    2398           0 :         if (!ok) {
    2399           0 :                 exit(1);
    2400             :         }
    2401             : 
    2402           0 :         return true;
    2403             : }
    2404             : 
    2405           0 : static void smbd_echo_exit(struct tevent_context *ev,
    2406             :                            struct tevent_fd *fde, uint16_t flags,
    2407             :                            void *private_data)
    2408             : {
    2409           0 :         DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
    2410           0 :         exit(0);
    2411             : }
    2412             : 
    2413             : static void smbd_echo_got_packet(struct tevent_req *req);
    2414             : 
    2415           0 : static void smbd_echo_loop(struct smbXsrv_connection *xconn,
    2416             :                            int parent_pipe)
    2417             : {
    2418             :         struct smbd_echo_state *state;
    2419             :         struct tevent_req *read_req;
    2420             : 
    2421           0 :         state = talloc_zero(xconn, struct smbd_echo_state);
    2422           0 :         if (state == NULL) {
    2423           0 :                 DEBUG(1, ("talloc failed\n"));
    2424           0 :                 return;
    2425             :         }
    2426           0 :         state->xconn = xconn;
    2427           0 :         state->parent_pipe = parent_pipe;
    2428           0 :         state->ev = samba_tevent_context_init(state);
    2429           0 :         if (state->ev == NULL) {
    2430           0 :                 DEBUG(1, ("samba_tevent_context_init failed\n"));
    2431           0 :                 TALLOC_FREE(state);
    2432           0 :                 return;
    2433             :         }
    2434           0 :         state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
    2435             :                                         TEVENT_FD_READ, smbd_echo_exit,
    2436             :                                         state);
    2437           0 :         if (state->parent_fde == NULL) {
    2438           0 :                 DEBUG(1, ("tevent_add_fd failed\n"));
    2439           0 :                 TALLOC_FREE(state);
    2440           0 :                 return;
    2441             :         }
    2442             : 
    2443           0 :         read_req = smbd_echo_read_send(state, state->ev, xconn);
    2444           0 :         if (read_req == NULL) {
    2445           0 :                 DEBUG(1, ("smbd_echo_read_send failed\n"));
    2446           0 :                 TALLOC_FREE(state);
    2447           0 :                 return;
    2448             :         }
    2449           0 :         tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
    2450             : 
    2451             :         while (true) {
    2452           0 :                 if (tevent_loop_once(state->ev) == -1) {
    2453           0 :                         DEBUG(1, ("tevent_loop_once failed: %s\n",
    2454             :                                   strerror(errno)));
    2455           0 :                         break;
    2456             :                 }
    2457             :         }
    2458           0 :         TALLOC_FREE(state);
    2459             : }
    2460             : 
    2461           0 : static void smbd_echo_got_packet(struct tevent_req *req)
    2462             : {
    2463           0 :         struct smbd_echo_state *state = tevent_req_callback_data(
    2464             :                 req, struct smbd_echo_state);
    2465             :         NTSTATUS status;
    2466           0 :         char *buf = NULL;
    2467           0 :         size_t buflen = 0;
    2468           0 :         uint32_t seqnum = 0;
    2469             :         bool reply;
    2470             : 
    2471           0 :         status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
    2472           0 :         TALLOC_FREE(req);
    2473           0 :         if (!NT_STATUS_IS_OK(status)) {
    2474           0 :                 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
    2475             :                           nt_errstr(status)));
    2476           0 :                 exit(1);
    2477             :         }
    2478             : 
    2479           0 :         reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
    2480           0 :         if (!reply) {
    2481             :                 size_t num_pending;
    2482             :                 struct iovec *tmp;
    2483             :                 struct iovec *iov;
    2484             : 
    2485           0 :                 num_pending = talloc_array_length(state->pending);
    2486           0 :                 tmp = talloc_realloc(state, state->pending, struct iovec,
    2487             :                                      num_pending+1);
    2488           0 :                 if (tmp == NULL) {
    2489           0 :                         DEBUG(1, ("talloc_realloc failed\n"));
    2490           0 :                         exit(1);
    2491             :                 }
    2492           0 :                 state->pending = tmp;
    2493             : 
    2494           0 :                 if (buflen >= smb_size) {
    2495             :                         /*
    2496             :                          * place the seqnum in the packet so that the main process
    2497             :                          * can reply with signing
    2498             :                          */
    2499           0 :                         SIVAL(buf, smb_ss_field, seqnum);
    2500           0 :                         SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
    2501             :                 }
    2502             : 
    2503           0 :                 iov = &state->pending[num_pending];
    2504           0 :                 iov->iov_base = talloc_move(state->pending, &buf);
    2505           0 :                 iov->iov_len = buflen;
    2506             : 
    2507           0 :                 DEBUG(10,("echo_handler[%d]: forward to main\n",
    2508             :                           (int)getpid()));
    2509           0 :                 smbd_echo_activate_writer(state);
    2510             :         }
    2511             : 
    2512           0 :         req = smbd_echo_read_send(state, state->ev, state->xconn);
    2513           0 :         if (req == NULL) {
    2514           0 :                 DEBUG(1, ("smbd_echo_read_send failed\n"));
    2515           0 :                 exit(1);
    2516             :         }
    2517           0 :         tevent_req_set_callback(req, smbd_echo_got_packet, state);
    2518           0 : }
    2519             : 
    2520             : 
    2521             : /*
    2522             :  * Handle SMBecho requests in a forked child process
    2523             :  */
    2524           0 : bool fork_echo_handler(struct smbXsrv_connection *xconn)
    2525             : {
    2526             :         int listener_pipe[2];
    2527             :         int res;
    2528             :         pid_t child;
    2529           0 :         bool use_mutex = false;
    2530             : 
    2531           0 :         res = pipe(listener_pipe);
    2532           0 :         if (res == -1) {
    2533           0 :                 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
    2534           0 :                 return false;
    2535             :         }
    2536             : 
    2537             : #ifdef HAVE_ROBUST_MUTEXES
    2538           0 :         use_mutex = tdb_runtime_check_for_robust_mutexes();
    2539             : 
    2540           0 :         if (use_mutex) {
    2541             :                 pthread_mutexattr_t a;
    2542             : 
    2543           0 :                 xconn->smb1.echo_handler.socket_mutex =
    2544           0 :                         anonymous_shared_allocate(sizeof(pthread_mutex_t));
    2545           0 :                 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
    2546           0 :                         DEBUG(1, ("Could not create mutex shared memory: %s\n",
    2547             :                                   strerror(errno)));
    2548           0 :                         goto fail;
    2549             :                 }
    2550             : 
    2551           0 :                 res = pthread_mutexattr_init(&a);
    2552           0 :                 if (res != 0) {
    2553           0 :                         DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
    2554             :                                   strerror(res)));
    2555           0 :                         goto fail;
    2556             :                 }
    2557           0 :                 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
    2558           0 :                 if (res != 0) {
    2559           0 :                         DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
    2560             :                                   strerror(res)));
    2561           0 :                         pthread_mutexattr_destroy(&a);
    2562           0 :                         goto fail;
    2563             :                 }
    2564           0 :                 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
    2565           0 :                 if (res != 0) {
    2566           0 :                         DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
    2567             :                                   strerror(res)));
    2568           0 :                         pthread_mutexattr_destroy(&a);
    2569           0 :                         goto fail;
    2570             :                 }
    2571           0 :                 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
    2572           0 :                 if (res != 0) {
    2573           0 :                         DEBUG(1, ("pthread_mutexattr_setrobust failed: "
    2574             :                                   "%s\n", strerror(res)));
    2575           0 :                         pthread_mutexattr_destroy(&a);
    2576           0 :                         goto fail;
    2577             :                 }
    2578           0 :                 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
    2579             :                                          &a);
    2580           0 :                 pthread_mutexattr_destroy(&a);
    2581           0 :                 if (res != 0) {
    2582           0 :                         DEBUG(1, ("pthread_mutex_init failed: %s\n",
    2583             :                                   strerror(res)));
    2584           0 :                         goto fail;
    2585             :                 }
    2586             :         }
    2587             : #endif
    2588             : 
    2589           0 :         if (!use_mutex) {
    2590           0 :                 xconn->smb1.echo_handler.socket_lock_fd =
    2591           0 :                         create_unlink_tmp(lp_lock_directory());
    2592           0 :                 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
    2593           0 :                         DEBUG(1, ("Could not create lock fd: %s\n",
    2594             :                                   strerror(errno)));
    2595           0 :                         goto fail;
    2596             :                 }
    2597             :         }
    2598             : 
    2599           0 :         child = fork();
    2600           0 :         if (child == 0) {
    2601             :                 NTSTATUS status;
    2602             : 
    2603           0 :                 close(listener_pipe[0]);
    2604           0 :                 set_blocking(listener_pipe[1], false);
    2605             : 
    2606           0 :                 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
    2607           0 :                                                 xconn->client->raw_ev_ctx,
    2608             :                                                 true,
    2609             :                                                 "smbd-echo");
    2610           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2611           0 :                         DEBUG(1, ("reinit_after_fork failed: %s\n",
    2612             :                                   nt_errstr(status)));
    2613           0 :                         exit(1);
    2614             :                 }
    2615           0 :                 initialize_password_db(true, xconn->client->raw_ev_ctx);
    2616           0 :                 smbd_echo_loop(xconn, listener_pipe[1]);
    2617           0 :                 exit(0);
    2618             :         }
    2619           0 :         close(listener_pipe[1]);
    2620           0 :         listener_pipe[1] = -1;
    2621           0 :         xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
    2622             : 
    2623           0 :         DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
    2624             : 
    2625             :         /*
    2626             :          * Without smb signing this is the same as the normal smbd
    2627             :          * listener. This needs to change once signing comes in.
    2628             :          */
    2629           0 :         xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
    2630             :                                         xconn->client->raw_ev_ctx,
    2631             :                                         xconn,
    2632             :                                         xconn->smb1.echo_handler.trusted_fd,
    2633             :                                         TEVENT_FD_READ,
    2634             :                                         smbd_server_echo_handler,
    2635             :                                         xconn);
    2636           0 :         if (xconn->smb1.echo_handler.trusted_fde == NULL) {
    2637           0 :                 DEBUG(1, ("event_add_fd failed\n"));
    2638           0 :                 goto fail;
    2639             :         }
    2640             : 
    2641           0 :         return true;
    2642             : 
    2643           0 : fail:
    2644           0 :         if (listener_pipe[0] != -1) {
    2645           0 :                 close(listener_pipe[0]);
    2646             :         }
    2647           0 :         if (listener_pipe[1] != -1) {
    2648           0 :                 close(listener_pipe[1]);
    2649             :         }
    2650           0 :         if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
    2651           0 :                 close(xconn->smb1.echo_handler.socket_lock_fd);
    2652             :         }
    2653             : #ifdef HAVE_ROBUST_MUTEXES
    2654           0 :         if (xconn->smb1.echo_handler.socket_mutex != NULL) {
    2655           0 :                 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
    2656           0 :                 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
    2657             :         }
    2658             : #endif
    2659           0 :         smbd_echo_init(xconn);
    2660             : 
    2661           0 :         return false;
    2662             : }
    2663             : 
    2664           0 : bool req_is_in_chain(const struct smb_request *req)
    2665             : {
    2666           0 :         if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
    2667             :                 /*
    2668             :                  * We're right now handling a subsequent request, so we must
    2669             :                  * be in a chain
    2670             :                  */
    2671           0 :                 return true;
    2672             :         }
    2673             : 
    2674           0 :         if (!smb1cli_is_andx_req(req->cmd)) {
    2675           0 :                 return false;
    2676             :         }
    2677             : 
    2678           0 :         if (req->wct < 2) {
    2679             :                 /*
    2680             :                  * Okay, an illegal request, but definitely not chained :-)
    2681             :                  */
    2682           0 :                 return false;
    2683             :         }
    2684             : 
    2685           0 :         return (CVAL(req->vwv+0, 0) != 0xFF);
    2686             : }

Generated by: LCOV version 1.13