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

Generated by: LCOV version 1.14