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

Generated by: LCOV version 1.14