LCOV - code coverage report
Current view: top level - source3/smbd - smb1_process.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 251 993 25.3 %
Date: 2024-02-14 10:14:15 Functions: 23 50 46.0 %

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

Generated by: LCOV version 1.14