Merge branch 'v3-2-test' of ssh://jra@git.samba.org/data/git/samba into v3-2-test
authorJeremy Allison <jra@samba.org>
Fri, 4 Jan 2008 20:59:36 +0000 (12:59 -0800)
committerJeremy Allison <jra@samba.org>
Fri, 4 Jan 2008 20:59:36 +0000 (12:59 -0800)
(This used to be commit 16224e8f4f22a8db0ed278d741a7706967f55335)

25 files changed:
source3/client/client.c
source3/include/smb.h
source3/include/smb_macros.h
source3/lib/dummysmbd.c
source3/lib/util_sock.c
source3/libsmb/smb_seal.c
source3/libsmb/smb_signing.c
source3/param/loadparm.c
source3/printing/nt_printing.c
source3/smbd/aio.c
source3/smbd/blocking.c
source3/smbd/error.c
source3/smbd/ipc.c
source3/smbd/lanman.c
source3/smbd/notify.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/oplock.c
source3/smbd/pipes.c
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/seal.c
source3/smbd/sesssetup.c
source3/smbd/trans2.c
source3/utils/smbfilter.c

index 2a86035cf0271408ec2f64009d1fb687f5edb003..fbcfa531ed41a60e8764924339e3e6c4ffc2c199 100644 (file)
@@ -4328,16 +4328,22 @@ static void readline_callback(void)
        timeout.tv_usec = 0;
        sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
 
-       /* We deliberately use receive_smb instead of
+       /* We deliberately use receive_smb_raw instead of
           client_receive_smb as we want to receive
           session keepalives and then drop them here.
        */
        if (FD_ISSET(cli->fd,&fds)) {
-               if (!receive_smb(cli->fd,cli->inbuf,0,&cli->smb_rw_error)) {
+               if (!receive_smb_raw(cli->fd,cli->inbuf,0,0,&cli->smb_rw_error)) {
                        DEBUG(0, ("Read from server failed, maybe it closed the "
                                "connection\n"));
                        return;
                }
+               if(CVAL(cli->inbuf,0) != SMBkeepalive) {
+                       DEBUG(0, ("Read from server "
+                               "returned unexpected packet!\n"));
+                       return;
+               }
+
                goto again;
        }
 
index 75fe31e041152f0df310c440cc678e45c9d4f1cc..49245eaa8302c5ce65d7aba832fa22762cdbec94 100644 (file)
@@ -659,6 +659,7 @@ typedef struct connection_struct {
        int num_files_open;
        unsigned int num_smb_operations; /* Count of smb operations on this tree. */
        int encrypt_level;
+       bool encrypted_tid;
 
        /* Semantics requested by the client or forced by the server config. */
        bool case_sensitive;
@@ -694,6 +695,8 @@ struct smb_request {
        const uint8 *inbuf;
        uint8 *outbuf;
        size_t unread_bytes;
+       bool encrypted;
+       connection_struct *conn;
 };
 
 /* Defines for the sent_oplock_break field above. */
@@ -757,6 +760,7 @@ struct pending_message_list {
        struct pending_message_list *next, *prev;
        struct timeval request_time; /* When was this first issued? */
        struct timeval end_time; /* When does this time out? */
+       bool encrypted;
        DATA_BLOB buf;
        DATA_BLOB private_data;
 };
index 9bacdce1db7d8ea817d52c997caa809823c7007a..3324f3fc02de6891fe6a7559c4153af266cefe80 100644 (file)
 #define SMB_LARGE_LKLEN_OFFSET_HIGH(indx) (12 + (20 * (indx)))
 #define SMB_LARGE_LKLEN_OFFSET_LOW(indx) (16 + (20 * (indx)))
 
-#define ERROR_DOS(class,code) error_packet(inbuf,outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__)
-#define ERROR_NT(status) error_packet(inbuf,outbuf,0,0,status,__LINE__,__FILE__)
-#define ERROR_FORCE_NT(status) error_packet(inbuf,outbuf,-1,-1,status,__LINE__,__FILE__)
-#define ERROR_BOTH(status,class,code) error_packet(inbuf,outbuf,class,code,status,__LINE__,__FILE__)
+#define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__)
+#define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__)
+#define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__)
+#define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__)
 
 #define reply_nterror(req,status) reply_nt_error(req,status,__LINE__,__FILE__)
 #define reply_force_nterror(req,status) reply_force_nt_error(req,status,__LINE__,__FILE__)
 #define _smb_setlen_large(buf,len) do { buf[0] = 0; buf[1] = ((len)&0xFF0000)>>16; \
         buf[2] = ((len)&0xFF00)>>8; buf[3] = (len)&0xFF; } while (0)
 
+#define ENCRYPTION_REQUIRED(conn) ((conn) ? ((conn)->encrypt_level == Required) : false)
+#define IS_CONN_ENCRYPTED(conn) ((conn) ? (conn)->encrypted_tid : false)
+
 /*******************************************************************
 find the difference in milliseconds between two struct timeval
 values
index 464ba9230636b55c06669cebd67dfb7e64b13248..dbe886e3d130c776753a41fbd93405621d0a4e52 100644 (file)
@@ -51,24 +51,3 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
 {
        return NT_STATUS_OK;
 }
-
-NTSTATUS srv_decrypt_buffer(char *buf)
-{
-        return NT_STATUS_OK;
-}
-
-NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out)
-{
-        *buf_out = buffer;
-        return NT_STATUS_OK;
-}
-
-void srv_free_enc_buffer(char *buf)
-{
-        ;
-}
-
-bool srv_encryption_on(void)
-{
-        return false;
-}
index b92cd3d624fe2454396da7e3911e0685bbc10772..945506ea7776a0fe9e4d252d758e342db4e2d04f 100644 (file)
@@ -1276,80 +1276,6 @@ ssize_t receive_smb_raw(int fd,
        return len;
 }
 
-/****************************************************************************
- Wrapper for receive_smb_raw().
- Checks the MAC on signed packets.
-****************************************************************************/
-
-bool receive_smb(int fd, char *buffer, unsigned int timeout, enum smb_read_errors *pre)
-{
-       if (receive_smb_raw(fd, buffer, timeout, 0, pre) < 0) {
-               return false;
-       }
-
-       if (srv_encryption_on()) {
-               NTSTATUS status = srv_decrypt_buffer(buffer);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("receive_smb: SMB decryption failed "
-                               "on incoming packet! Error %s\n",
-                               nt_errstr(status) ));
-                       cond_set_smb_read_error(pre, SMB_READ_BAD_DECRYPT);
-                       return false;
-               }
-       }
-
-       /* Check the incoming SMB signature. */
-       if (!srv_check_sign_mac(buffer, true)) {
-               DEBUG(0, ("receive_smb: SMB Signature verification "
-                       "failed on incoming packet!\n"));
-               cond_set_smb_read_error(pre,SMB_READ_BAD_SIG);
-               return false;
-       }
-
-       return true;
-}
-
-/****************************************************************************
- Send an smb to a fd.
-****************************************************************************/
-
-bool send_smb(int fd, char *buffer)
-{
-       size_t len;
-       size_t nwritten=0;
-       ssize_t ret;
-       char *buf_out = buffer;
-
-       /* Sign the outgoing packet if required. */
-       srv_calculate_sign_mac(buf_out);
-
-       if (srv_encryption_on()) {
-               NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("send_smb: SMB encryption failed "
-                               "on outgoing packet! Error %s\n",
-                               nt_errstr(status) ));
-                       return false;
-               }
-       }
-
-       len = smb_len(buf_out) + 4;
-
-       while (nwritten < len) {
-               ret = write_data(fd,buf_out+nwritten,len - nwritten);
-               if (ret <= 0) {
-                       DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
-                               (int)len,(int)ret, strerror(errno) ));
-                       srv_free_enc_buffer(buf_out);
-                       return false;
-               }
-               nwritten += ret;
-       }
-
-       srv_free_enc_buffer(buf_out);
-       return true;
-}
-
 /****************************************************************************
  Open a socket of the specified type, port, and address for incoming data.
 ****************************************************************************/
index 055a27d05af546c49d479458e09bc037f1f00f99..b5befbf7cdcecba0e7adc2fd83adf28f781927a2 100644 (file)
  Pull out the encryption context for this packet. 0 means global context.
 ******************************************************************************/
 
-NTSTATUS get_enc_ctx_num(const char *buf, uint16 *p_enc_ctx_num)
+NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
 {
        if (smb_len(buf) < 8) {
                return NT_STATUS_INVALID_BUFFER_SIZE;
        }
 
-       if (buf[4] == (char)0xFF) {
+       if (buf[4] == 0xFF) {
                if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
                        /* Not an encrypted buffer. */
                        return NT_STATUS_NOT_FOUND;
@@ -93,8 +93,8 @@ NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
 
        memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
 
-       /* Reset the length. */
-       _smb_setlen(buf,data_len + 4);
+       /* Reset the length and overwrite the header. */
+       smb_setlen(buf,data_len + 4);
 
        SAFE_FREE(inbuf);
        return NT_STATUS_OK;
@@ -203,7 +203,8 @@ static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_sta
        }
 
        memcpy(buf + 8, out_buf.value, out_buf.length);
-       _smb_setlen(buf, out_buf.length + 4);
+       /* Reset the length and overwrite the header. */
+       smb_setlen(buf, out_buf.length + 4);
 
        gss_release_buffer(&minor, &out_buf);
        return NT_STATUS_OK;
@@ -440,9 +441,9 @@ void cli_free_enc_buffer(struct cli_state *cli, char *buf)
 {
        /* We know this is an smb buffer, and we
         * didn't malloc, only copy, for a keepalive,
-        * so ignore session keepalives. */
+        * so ignore non-session messages. */
 
-       if(CVAL(buf,0) == SMBkeepalive) {
+       if(CVAL(buf,0)) {
                return;
        }
 
@@ -461,12 +462,12 @@ NTSTATUS cli_decrypt_message(struct cli_state *cli)
        NTSTATUS status;
        uint16 enc_ctx_num;
 
-       /* Ignore session keepalives. */
-       if(CVAL(cli->inbuf,0) == SMBkeepalive) {
+       /* Ignore non-session messages. */
+       if(CVAL(cli->inbuf,0)) {
                return NT_STATUS_OK;
        }
 
-       status = get_enc_ctx_num(cli->inbuf, &enc_ctx_num);
+       status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -484,8 +485,8 @@ NTSTATUS cli_decrypt_message(struct cli_state *cli)
 
 NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
 {
-       /* Ignore session keepalives. */
-       if(CVAL(cli->outbuf,0) == SMBkeepalive) {
+       /* Ignore non-session messages. */
+       if(CVAL(cli->outbuf,0)) {
                return NT_STATUS_OK;
        }
 
index d5cbe3b12535aec2eb323184b30c83a7546fb10b..f03c21bd0e0c59e6a569c8afaebb0b257ed29354 100644 (file)
@@ -745,8 +745,8 @@ bool srv_oplock_set_signing(bool onoff)
 
 bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
 {
-       /* Check if it's a session keepalive. */
-       if(CVAL(inbuf,0) == SMBkeepalive) {
+       /* Check if it's a non-session message. */
+       if(CVAL(inbuf,0)) {
                return True;
        }
 
@@ -759,8 +759,8 @@ bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
 
 void srv_calculate_sign_mac(char *outbuf)
 {
-       /* Check if it's a session keepalive. */
-       if(CVAL(outbuf,0) == SMBkeepalive) {
+       /* Check if it's a non-session message. */
+       if(CVAL(outbuf,0)) {
                return;
        }
 
index 16e937200983ef6110d816da9925482cdbd9673b..29166cf02ece95602ce32717900ae319eef74174 100644 (file)
@@ -6213,7 +6213,7 @@ uint32 lp_get_spoolss_state( void )
 }
 
 /*******************************************************************
- Ensure we don't use sendfile if server smb signing or selaing is active.
+ Ensure we don't use sendfile if server smb signing is active.
 ********************************************************************/
 
 bool lp_use_sendfile(int snum)
@@ -6224,8 +6224,7 @@ bool lp_use_sendfile(int snum)
        }
        return (_lp_use_sendfile(snum) &&
                        (get_remote_arch() != RA_WIN95) &&
-                       !srv_is_signing_active() &&
-                       !srv_encryption_on());
+                       !srv_is_signing_active());
 }
 
 /*******************************************************************
index f115fba91f0245da66f2f83430a9c4a5ba57ca77..bae32e89f75a4edded53f52bc839ab8417f648dd 100644 (file)
@@ -1867,7 +1867,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                goto err_exit;
        }
 
-       create_directory(conn, new_dir);
+       create_directory(conn, NULL, new_dir);
 
        /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
         * listed for this driver which has already been moved, skip it (note:
index a439c3a4f0517c8871ef8306e80e74a38365393c..bc1761b0fdaded0c8615e00ab966010c82dbdb85 100644 (file)
@@ -236,7 +236,7 @@ bool schedule_aio_read_and_X(connection_struct *conn,
        }
 
        construct_reply_common((char *)req->inbuf, aio_ex->outbuf);
-       srv_set_message((const char *)req->inbuf, aio_ex->outbuf, 12, 0, True);
+       srv_set_message(aio_ex->outbuf, 12, 0, True);
        SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */
 
        a = &aio_ex->acb;
@@ -356,8 +356,9 @@ bool schedule_aio_write_and_X(connection_struct *conn,
                SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite);
                 SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
                show_msg(aio_ex->outbuf);
-               if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) {
-                       exit_server_cleanly("handle_aio_write: send_smb "
+               if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
+                               IS_CONN_ENCRYPTED(fsp->conn))) {
+                       exit_server_cleanly("handle_aio_write: srv_send_smb "
                                            "failed.");
                }
                DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
@@ -387,7 +388,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
        int ret = 0;
        int outsize;
        char *outbuf = aio_ex->outbuf;
-       const char *inbuf = aio_ex->inbuf;
        char *data = smb_buf(outbuf);
        ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
 
@@ -410,9 +410,9 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
 
                ret = errno;
                ERROR_NT(map_nt_error_from_unix(ret));
-               outsize = srv_set_message(inbuf,outbuf,0,0,true);
+               outsize = srv_set_message(outbuf,0,0,true);
        } else {
-               outsize = srv_set_message(inbuf, outbuf,12,nread,False);
+               outsize = srv_set_message(outbuf,12,nread,False);
                SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
                SSVAL(outbuf,smb_vwv5,nread);
                SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
@@ -425,10 +425,11 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
                            (int)aio_ex->acb.aio_nbytes, (int)nread ) );
 
        }
-       _smb_setlen(outbuf,outsize - 4);
+       smb_setlen(outbuf,outsize - 4);
        show_msg(outbuf);
-       if (!send_smb(smbd_server_fd(),outbuf)) {
-               exit_server_cleanly("handle_aio_read_complete: send_smb "
+       if (!srv_send_smb(smbd_server_fd(),outbuf,
+                       IS_CONN_ENCRYPTED(aio_ex->fsp->conn))) {
+               exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
                                    "failed.");
        }
 
@@ -497,7 +498,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
 
                ret = errno;
                ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull);
-               srv_set_message(inbuf,outbuf,0,0,true);
+               srv_set_message(outbuf,0,0,true);
         } else {
                bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0);
                NTSTATUS status;
@@ -516,15 +517,15 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
                        ret = errno;
                        ERROR_BOTH(map_nt_error_from_unix(ret),
                                   ERRHRD, ERRdiskfull);
-                       srv_set_message(inbuf,outbuf,0,0,true);
+                       srv_set_message(outbuf,0,0,true);
                        DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
                                fsp->fsp_name, nt_errstr(status) ));
                }
        }
 
        show_msg(outbuf);
-       if (!send_smb(smbd_server_fd(),outbuf)) {
-               exit_server_cleanly("handle_aio_write: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn))) {
+               exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
        }
 
        DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
index 0078bb7d13dd11226af0c513c6800539df01dede..c56f635dde447eea3b2b09a8425473477a073a8b 100644 (file)
@@ -41,6 +41,7 @@ typedef struct _blocking_lock_record {
        enum brl_type lock_type;
        char *inbuf;
        int length;
+       bool encrypted;
 } blocking_lock_record;
 
 /* dlink list we store pending lock records on. */
@@ -149,7 +150,7 @@ static bool recalc_brl_timeout(void)
 ****************************************************************************/
 
 bool push_blocking_lock_request( struct byte_range_lock *br_lck,
-               const char *inbuf, int length,
+               const struct smb_request *req,
                files_struct *fsp,
                int lock_timeout,
                int lock_num,
@@ -161,6 +162,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
                uint32 blocking_pid)
 {
        static bool set_lock_msg;
+       size_t length = smb_len(req->inbuf)+4;
        blocking_lock_record *blr;
        NTSTATUS status;
 
@@ -188,7 +190,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
                return False;
        }
 
-       blr->com_type = CVAL(inbuf,smb_com);
+       blr->com_type = CVAL(req->inbuf,smb_com);
        blr->fsp = fsp;
        if (lock_timeout == -1) {
                blr->expire_time.tv_sec = 0;
@@ -204,8 +206,9 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
        blr->lock_type = lock_type;
        blr->offset = offset;
        blr->count = count;
-       memcpy(blr->inbuf, inbuf, length);
+       memcpy(blr->inbuf, req->inbuf, length);
        blr->length = length;
+       blr->encrypted = req->encrypted;
 
        /* Add a pending lock record for this. */
        status = brl_lock(smbd_messaging_context(), br_lck,
@@ -242,7 +245,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
                blr->fsp->fnum, blr->fsp->fsp_name ));
 
        /* Push the MID of this packet on the signing queue. */
-       srv_defer_sign_response(SVAL(inbuf,smb_mid));
+       srv_defer_sign_response(SVAL(req->inbuf,smb_mid));
 
        return True;
 }
@@ -259,7 +262,7 @@ static void reply_lockingX_success(blocking_lock_record *blr)
                smb_panic("Could not allocate smb_request");
        }
 
-       init_smb_request(req, (uint8 *)blr->inbuf, 0);
+       init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted);
        reply_outbuf(req, 2, 0);
 
        /*
@@ -272,8 +275,10 @@ static void reply_lockingX_success(blocking_lock_record *blr)
 
        chain_reply(req);
 
-       if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) {
-               exit_server_cleanly("send_blocking_reply: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),
+                       (char *)req->outbuf,
+                       IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+               exit_server_cleanly("send_blocking_reply: srv_send_smb failed.");
        }
 }
 
@@ -309,8 +314,9 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat
        }
 
        ERROR_NT(status);
-       if (!send_smb(smbd_server_fd(),outbuf)) {
-               exit_server_cleanly("generic_blocking_lock_error: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),outbuf,
+                       IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+               exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
        }
 }
 
@@ -388,8 +394,10 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status
                         */
                        SCVAL(outbuf,smb_com,SMBtrans2);
                        ERROR_NT(status);
-                       if (!send_smb(smbd_server_fd(),outbuf)) {
-                               exit_server_cleanly("blocking_lock_reply_error: send_smb failed.");
+                       if (!srv_send_smb(smbd_server_fd(),
+                                       outbuf,
+                                       IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+                               exit_server_cleanly("blocking_lock_reply_error: srv_send_smb failed.");
                        }
                        break;
                }
@@ -531,12 +539,12 @@ static bool process_trans2(blocking_lock_record *blr)
                return True;
        }
 
-       init_smb_request(req, (uint8 *)blr->inbuf, 0);
+       init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted);
 
        SCVAL(req->inbuf, smb_com, SMBtrans2);
        SSVAL(params,0,0);
        /* Fake up max_data_bytes here - we know it fits. */
-       send_trans2_replies(req, params, 2, NULL, 0, 0xffff);
+       send_trans2_replies(blr->fsp->conn, req, params, 2, NULL, 0, 0xffff);
        return True;
 }
 
index c669e741461536ec687629b4952c188c8fabbae7..de2de088ec222f30d0c7328bf628217173b49a77 100644 (file)
@@ -81,9 +81,9 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu
        }
 }
 
-int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
+int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
 {
-       int outsize = srv_set_message(inbuf, outbuf,0,0,True);
+       int outsize = srv_set_message(outbuf,0,0,True);
        error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
        return outsize;
 }
index f28016ccb3f3a34ace57bd0f47db1a0d374f4860..a89f5cbbfe2bd9f2e5a4854d626001729ad01a64 100644 (file)
@@ -30,7 +30,7 @@ extern int max_send;
 
 #define NERR_notsupported 50
 
-static void api_no_reply(struct smb_request *req);
+static void api_no_reply(connection_struct *conn, struct smb_request *req);
 
 /*******************************************************************
  copies parameters and data, as needed, into the smb buffer
@@ -81,7 +81,8 @@ static void copy_trans_params_and_data(char *outbuf, int align,
  Send a trans reply.
  ****************************************************************************/
 
-void send_trans_reply(struct smb_request *req,
+void send_trans_reply(connection_struct *conn,
+                       struct smb_request *req,
                      char *rparam, int rparam_len,
                      char *rdata, int rdata_len,
                      bool buffer_too_large)
@@ -129,8 +130,10 @@ void send_trans_reply(struct smb_request *req,
        }
 
        show_msg((char *)req->outbuf);
-       if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
-               exit_server_cleanly("send_trans_reply: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),
+                       (char *)req->outbuf,
+                       IS_CONN_ENCRYPTED(conn)))
+               exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
 
        TALLOC_FREE(req->outbuf);
 
@@ -175,8 +178,10 @@ void send_trans_reply(struct smb_request *req,
                }
 
                show_msg((char *)req->outbuf);
-               if (!send_smb(smbd_server_fd(), (char *)req->outbuf))
-                       exit_server_cleanly("send_trans_reply: send_smb failed.");
+               if (!srv_send_smb(smbd_server_fd(),
+                               (char *)req->outbuf,
+                               IS_CONN_ENCRYPTED(conn)))
+                       exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
 
                tot_data_sent  += this_ldata;
                tot_param_sent += this_lparam;
@@ -188,7 +193,7 @@ void send_trans_reply(struct smb_request *req,
  Start the first part of an RPC reply which began with an SMBtrans request.
 ****************************************************************************/
 
-static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p)
+static void api_rpc_trans_reply(connection_struct *conn, struct smb_request *req, smb_np_struct *p)
 {
        bool is_data_outstanding;
        char *rdata = (char *)SMB_MALLOC(p->max_trans_reply);
@@ -203,11 +208,11 @@ static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p)
        if((data_len = read_from_pipe( p, rdata, p->max_trans_reply,
                                        &is_data_outstanding)) < 0) {
                SAFE_FREE(rdata);
-               api_no_reply(req);
+               api_no_reply(conn,req);
                return;
        }
 
-       send_trans_reply(req, NULL, 0, rdata, data_len, is_data_outstanding);
+       send_trans_reply(conn, req, NULL, 0, rdata, data_len, is_data_outstanding);
        SAFE_FREE(rdata);
        return;
 }
@@ -216,7 +221,7 @@ static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p)
  WaitNamedPipeHandleState 
 ****************************************************************************/
 
-static void api_WNPHS(struct smb_request *req, smb_np_struct *p,
+static void api_WNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p,
                      char *param, int param_len)
 {
        uint16 priority;
@@ -231,10 +236,10 @@ static void api_WNPHS(struct smb_request *req, smb_np_struct *p,
 
        if (wait_rpc_pipe_hnd_state(p, priority)) {
                /* now send the reply */
-               send_trans_reply(req, NULL, 0, NULL, 0, False);
+               send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
                return;
        }
-       api_no_reply(req);
+       api_no_reply(conn,req);
 }
 
 
@@ -242,7 +247,7 @@ static void api_WNPHS(struct smb_request *req, smb_np_struct *p,
  SetNamedPipeHandleState 
 ****************************************************************************/
 
-static void api_SNPHS(struct smb_request *req, smb_np_struct *p,
+static void api_SNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p,
                      char *param, int param_len)
 {
        uint16 id;
@@ -257,10 +262,10 @@ static void api_SNPHS(struct smb_request *req, smb_np_struct *p,
 
        if (set_rpc_pipe_hnd_state(p, id)) {
                /* now send the reply */
-               send_trans_reply(req, NULL, 0, NULL, 0, False);
+               send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
                return;
        }
-       api_no_reply(req);
+       api_no_reply(conn,req);
 }
 
 
@@ -268,7 +273,7 @@ static void api_SNPHS(struct smb_request *req, smb_np_struct *p,
  When no reply is generated, indicate unsupported.
  ****************************************************************************/
 
-static void api_no_reply(struct smb_request *req)
+static void api_no_reply(connection_struct *conn, struct smb_request *req)
 {
        char rparam[4];
 
@@ -279,7 +284,7 @@ static void api_no_reply(struct smb_request *req)
        DEBUG(3,("Unsupported API fd command\n"));
 
        /* now send the reply */
-       send_trans_reply(req, rparam, 4, NULL, 0, False);
+       send_trans_reply(conn, req, rparam, 4, NULL, 0, False);
 
        return;
 }
@@ -321,7 +326,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
                        /* Win9x does this call with a unicode pipe name, not a pnum. */
                        /* Just return success for now... */
                        DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
-                       send_trans_reply(req, NULL, 0, NULL, 0, False);
+                       send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
                        return;
                }
 
@@ -349,18 +354,18 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
                /* dce/rpc command */
                reply = write_to_pipe(p, data, tdscnt);
                if (!reply) {
-                       api_no_reply(req);
+                       api_no_reply(conn, req);
                        return;
                }
-               api_rpc_trans_reply(req, p);
+               api_rpc_trans_reply(conn, req, p);
                break;
        case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
                /* Wait Named Pipe Handle state */
-               api_WNPHS(req, p, params, tpscnt);
+               api_WNPHS(conn, req, p, params, tpscnt);
                break;
        case TRANSACT_SETNAMEDPIPEHANDLESTATE:
                /* Set Named Pipe Handle state */
-               api_SNPHS(req, p, params, tpscnt);
+               api_SNPHS(conn, req, p, params, tpscnt);
                break;
        default:
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -472,8 +477,10 @@ static void handle_trans(connection_struct *conn, struct smb_request *req,
                   state->max_data_return,
                   state->max_param_return);
 
-       if (state->close_on_completion)
+       if (state->close_on_completion) {
                close_cnum(conn,state->vuid);
+               req->conn = NULL;
+       }
 
        return;
 }
index 3ab216c062acda94dd08dffc00bf8c88e5dc223b..5a6df1f13911dd98e8210b800061cd1e5ce8aa36 100644 (file)
@@ -4605,7 +4605,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
 
        /* If api_Unsupported returns false we can't return anything. */
        if (reply) {
-               send_trans_reply(req, rparam, rparam_len,
+               send_trans_reply(conn, req, rparam, rparam_len,
                                 rdata, rdata_len, False);
        }
 
index baab48f77ef4713865bc7b27a003c9c77abc122d..72872108029b5e1a4acac15a88ac1ad524a202d5 100644 (file)
@@ -128,10 +128,10 @@ static bool notify_marshall_changes(int num_changes,
  Setup the common parts of the return packet and send it.
 *****************************************************************************/
 
-static void change_notify_reply_packet(const uint8 *request_buf,
+static void change_notify_reply_packet(connection_struct *conn,
+                               const uint8 *request_buf,
                                       NTSTATUS error_code)
 {
-       const char *inbuf = (const char *)request_buf;
        char outbuf[smb_size+38];
 
        memset(outbuf, '\0', sizeof(outbuf));
@@ -143,15 +143,18 @@ static void change_notify_reply_packet(const uint8 *request_buf,
         * Seems NT needs a transact command with an error code
         * in it. This is a longer packet than a simple error.
         */
-       srv_set_message((const char *)request_buf, outbuf,18,0,False);
+       srv_set_message(outbuf,18,0,False);
 
        show_msg(outbuf);
-       if (!send_smb(smbd_server_fd(),outbuf))
-               exit_server_cleanly("change_notify_reply_packet: send_smb "
+       if (!srv_send_smb(smbd_server_fd(),
+                       outbuf,
+                       IS_CONN_ENCRYPTED(conn)))
+               exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
                                    "failed.");
 }
 
-void change_notify_reply(const uint8 *request_buf, uint32 max_param,
+void change_notify_reply(connection_struct *conn,
+                       const uint8 *request_buf, uint32 max_param,
                         struct notify_change_buf *notify_buf)
 {
        prs_struct ps;
@@ -159,7 +162,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param,
        uint8 tmp_request[smb_size];
 
        if (notify_buf->num_changes == -1) {
-               change_notify_reply_packet(request_buf, NT_STATUS_OK);
+               change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
                notify_buf->num_changes = 0;
                return;
        }
@@ -172,12 +175,12 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param,
                 * We exceed what the client is willing to accept. Send
                 * nothing.
                 */
-               change_notify_reply_packet(request_buf, NT_STATUS_OK);
+               change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
                goto done;
        }
 
        if (!(req = talloc(talloc_tos(), struct smb_request))) {
-               change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
+               change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY);
                goto done;
        }
 
@@ -190,9 +193,9 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param,
        smb_setlen((char *)tmp_request, smb_size);
        SCVAL(tmp_request, smb_wct, 0);
 
-       init_smb_request(req, tmp_request,0);
+       init_smb_request(req, tmp_request,0, conn->encrypted_tid);
 
-       send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps),
+       send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps),
                        prs_offset(&ps), NULL, 0);
 
  done:
@@ -243,9 +246,10 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
        return status;
 }
 
-NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param,
-                                  uint32 filter, bool recursive,
-                                  struct files_struct *fsp)
+NTSTATUS change_notify_add_request(const struct smb_request *req,
+                               uint32 max_param,
+                               uint32 filter, bool recursive,
+                               struct files_struct *fsp)
 {
        struct notify_change_request *request = NULL;
        struct notify_mid_map *map = NULL;
@@ -259,7 +263,7 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param,
        request->mid_map = map;
        map->req = request;
 
-       memcpy(request->request_buf, inbuf, sizeof(request->request_buf));
+       memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf));
        request->max_param = max_param;
        request->filter = filter;
        request->fsp = fsp;
@@ -268,11 +272,11 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param,
        DLIST_ADD_END(fsp->notify->requests, request,
                      struct notify_change_request *);
 
-       map->mid = SVAL(inbuf, smb_mid);
+       map->mid = SVAL(req->inbuf, smb_mid);
        DLIST_ADD(notify_changes_by_mid, map);
 
        /* Push the MID of this packet on the signing queue. */
-       srv_defer_sign_response(SVAL(inbuf,smb_mid));
+       srv_defer_sign_response(SVAL(req->inbuf,smb_mid));
 
        return NT_STATUS_OK;
 }
@@ -325,7 +329,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid)
                return;
        }
 
-       change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED);
+       change_notify_reply_packet(map->req->fsp->conn,
+                       map->req->request_buf, NT_STATUS_CANCELLED);
        change_notify_remove_request(map->req);
 }
 
@@ -341,7 +346,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp,
        }
 
        while (fsp->notify->requests != NULL) {
-               change_notify_reply_packet(
+               change_notify_reply_packet(fsp->conn,
                        fsp->notify->requests->request_buf, status);
                change_notify_remove_request(fsp->notify->requests);
        }
@@ -435,7 +440,8 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
         * TODO: do we have to walk the lists of requests pending?
         */
 
-       change_notify_reply(fsp->notify->requests->request_buf,
+       change_notify_reply(fsp->conn,
+                       fsp->notify->requests->request_buf,
                            fsp->notify->requests->max_param,
                            fsp->notify);
 
index 69772b6becc6148e0d208194d3fa2e8e3377eeb6..8ac0217dcd8e0ef6c414b44892f4beccdc4ab3e0 100644 (file)
@@ -66,7 +66,8 @@ static char *nttrans_realloc(char **ptr, size_t size)
  HACK ! Always assumes smb_setup field is zero.
 ****************************************************************************/
 
-void send_nt_replies(struct smb_request *req, NTSTATUS nt_error,
+void send_nt_replies(connection_struct *conn,
+                       struct smb_request *req, NTSTATUS nt_error,
                     char *params, int paramsize,
                     char *pdata, int datasize)
 {
@@ -242,8 +243,10 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error,
 
                /* Send the packet */
                show_msg((char *)req->outbuf);
-               if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) {
-                       exit_server_cleanly("send_nt_replies: send_smb failed.");
+               if (!srv_send_smb(smbd_server_fd(),
+                               (char *)req->outbuf,
+                               IS_CONN_ENCRYPTED(conn))) {
+                       exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
                }
 
                TALLOC_FREE(req->outbuf);
@@ -726,7 +729,7 @@ static void do_nt_transact_create_pipe(connection_struct *conn,
        DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
 
        /* Send the required number of replies */
-       send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0);
+       send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
 
        return;
 }
@@ -1080,7 +1083,7 @@ static void call_nt_transact_create(connection_struct *conn,
        DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
 
        /* Send the required number of replies */
-       send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0);
+       send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
 
        return;
 }
@@ -1474,7 +1477,7 @@ static void call_nt_transact_notify_change(connection_struct *conn,
                 * here.
                 */
 
-               change_notify_reply(req->inbuf, max_param_count, fsp->notify);
+               change_notify_reply(fsp->conn, req->inbuf, max_param_count, fsp->notify);
 
                /*
                 * change_notify_reply() above has independently sent its
@@ -1487,7 +1490,9 @@ static void call_nt_transact_notify_change(connection_struct *conn,
         * No changes pending, queue the request
         */
 
-       status = change_notify_add_request(req->inbuf, max_param_count, filter,
+       status = change_notify_add_request(req,
+                       max_param_count,
+                       filter,
                        recursive, fsp);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -1554,7 +1559,7 @@ static void call_nt_transact_rename(connection_struct *conn,
        /*
         * Rename was successful.
         */
-       send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+       send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
 
        DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
                 fsp->fsp_name, new_name));
@@ -1657,7 +1662,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
        SIVAL(params,0,(uint32)sd_size);
 
        if (max_data_count < sd_size) {
-               send_nt_replies(req, NT_STATUS_BUFFER_TOO_SMALL,
+               send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
                                params, 4, *ppdata, 0);
                TALLOC_FREE(frame);
                return;
@@ -1686,7 +1691,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
        SMB_ASSERT(sd_size == blob.length);
        memcpy(data, blob.data, sd_size);
 
-       send_nt_replies(req, NT_STATUS_OK, params, 4, data, (int)sd_size);
+       send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size);
 
        TALLOC_FREE(frame);
        return;
@@ -1744,7 +1749,7 @@ static void call_nt_transact_set_security_desc(connection_struct *conn,
        }
 
   done:
-       send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+       send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
        return;
 }
 
@@ -1793,7 +1798,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
                   so we can know if we need to pre-allocate or not */
 
                DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
-               send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+               send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
                return;
 
        case FSCTL_CREATE_OR_GET_OBJECT_ID:
@@ -1819,7 +1824,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
                push_file_id_16(pdata, &fsp->file_id);
                memcpy(pdata+16,create_volume_objectid(conn,objid),16);
                push_file_id_16(pdata+32, &fsp->file_id);
-               send_nt_replies(req, NT_STATUS_OK, NULL, 0,
+               send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0,
                                pdata, data_count);
                return;
        }
@@ -1964,7 +1969,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
 
                talloc_destroy(shadow_data->mem_ctx);
 
-               send_nt_replies(req, NT_STATUS_OK, NULL, 0,
+               send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0,
                                pdata, data_count);
 
                return;
@@ -2020,7 +2025,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
                 */
 
                /* this works for now... */
-               send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+               send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
                return;
        }
        default:
@@ -2306,7 +2311,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
                        break;
        }
 
-       send_nt_replies(req, nt_status, params, param_len,
+       send_nt_replies(conn, req, nt_status, params, param_len,
                        pdata, data_len);
 }
 
@@ -2436,7 +2441,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
                return;
        }
 
-       send_nt_replies(req, NT_STATUS_OK, params, param_len,
+       send_nt_replies(conn, req, NT_STATUS_OK, params, param_len,
                        pdata, data_len);
 }
 #endif /* HAVE_SYS_QUOTAS */
index b6e6adde8a18f661ba271ec1594a732eacbf99d3..e3fae02b83291d6892380cf7cbef87e82dd7df2d 100644 (file)
@@ -2267,7 +2267,7 @@ NTSTATUS open_directory(connection_struct *conn,
        return NT_STATUS_OK;
 }
 
-NTSTATUS create_directory(connection_struct *conn, const char *directory)
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory)
 {
        NTSTATUS status;
        SMB_STRUCT_STAT sbuf;
@@ -2275,7 +2275,7 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory)
 
        SET_STAT_INVALID(sbuf);
        
-       status = open_directory(conn, NULL, directory, &sbuf,
+       status = open_directory(conn, req, directory, &sbuf,
                                FILE_READ_ATTRIBUTES, /* Just a stat open */
                                FILE_SHARE_NONE, /* Ignored for stat opens */
                                FILE_CREATE,
index 8a5b1f4ecd5397d95a6a844212d6db84d1ffc017..277e07c178e83f87f09e772f746b80c38710b927 100644 (file)
@@ -252,13 +252,7 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx,
        }
 
        memset(result,'\0',smb_size);
-       if (!srv_encryption_on()) {
-               cli_set_message(result,8,0,true);
-       } else {
-               char inbuf[8];
-               smb_set_enclen(inbuf,4,srv_enc_ctx());
-               srv_set_message(inbuf,result,8,0,true);
-       }
+       srv_set_message(result,8,0,true);
        SCVAL(result,smb_com,SMBlockingX);
        SSVAL(result,smb_tid,fsp->conn->cnum);
        SSVAL(result,smb_pid,0xFFFF);
@@ -455,8 +449,10 @@ static void process_oplock_async_level2_break_message(struct messaging_context *
        sign_state = srv_oplock_set_signing(False);
 
        show_msg(break_msg);
-       if (!send_smb(smbd_server_fd(), break_msg)) {
-               exit_server_cleanly("oplock_break: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),
+                       break_msg,
+                       IS_CONN_ENCRYPTED(fsp->conn))) {
+               exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
        /* Restore the sign state to what it was. */
@@ -560,8 +556,10 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
        sign_state = srv_oplock_set_signing(False);
 
        show_msg(break_msg);
-       if (!send_smb(smbd_server_fd(), break_msg)) {
-               exit_server_cleanly("oplock_break: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),
+                       break_msg,
+                       IS_CONN_ENCRYPTED(fsp->conn))) {
+               exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
        /* Restore the sign state to what it was. */
@@ -637,8 +635,10 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
        sign_state = srv_oplock_set_signing(False);
 
        show_msg(break_msg);
-       if (!send_smb(smbd_server_fd(), break_msg)) {
-               exit_server_cleanly("oplock_break: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),
+                       break_msg,
+                       IS_CONN_ENCRYPTED(fsp->conn))) {
+               exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
        /* Restore the sign state to what it was. */
index 88b67c03e57aa658d6248df315b0c85e6a5b60ff..6b4b83d97dd446006a2c5598a426d403f8eba189 100644 (file)
@@ -291,8 +291,7 @@ void reply_pipe_read_and_X(struct smb_request *req)
                return;
        }
 
-       srv_set_message((const char *)req->inbuf,
-               (char *)req->outbuf, 12, nread, False);
+       srv_set_message((char *)req->outbuf, 12, nread, False);
   
        SSVAL(req->outbuf,smb_vwv5,nread);
        SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf));
index 48a6d18bc92c6432c909079536b8b8e1824c5699..32d1d058e36f31fc9fcf6e9b3584149e8b7d6e80 100644 (file)
@@ -50,14 +50,52 @@ enum smb_read_errors *get_srv_read_error(void)
        return &smb_read_error;
 }
 
+/****************************************************************************
+ Send an smb to a fd.
+****************************************************************************/
+
+bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
+{
+       size_t len;
+       size_t nwritten=0;
+       ssize_t ret;
+       char *buf_out = buffer;
+
+       /* Sign the outgoing packet if required. */
+       srv_calculate_sign_mac(buf_out);
+
+       if (do_encrypt) {
+               NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("send_smb: SMB encryption failed "
+                               "on outgoing packet! Error %s\n",
+                               nt_errstr(status) ));
+                       return false;
+               }
+       }
+
+       len = smb_len(buf_out) + 4;
+
+       while (nwritten < len) {
+               ret = write_data(fd,buf_out+nwritten,len - nwritten);
+               if (ret <= 0) {
+                       DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+                               (int)len,(int)ret, strerror(errno) ));
+                       srv_free_enc_buffer(buf_out);
+                       return false;
+               }
+               nwritten += ret;
+       }
+
+       srv_free_enc_buffer(buf_out);
+       return true;
+}
+
 /*******************************************************************
  Setup the word count and byte count for a smb message.
- copying the '0xFF X X X' bytes from incoming
- buffer (so we copy any encryption context).
 ********************************************************************/
 
-int srv_set_message(const char *frombuf,
-                        char *buf,
+int srv_set_message(char *buf,
                         int num_words,
                         int num_bytes,
                         bool zero)
@@ -67,22 +105,14 @@ int srv_set_message(const char *frombuf,
        }
        SCVAL(buf,smb_wct,num_words);
        SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
-       _smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
-       if (buf != frombuf) {
-               memcpy(buf+4, frombuf+4, 4);
-       }
+       smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
        return (smb_size + num_words*2 + num_bytes);
 }
 
-static bool valid_smb_header(const char *inbuf)
+static bool valid_smb_header(const uint8_t *inbuf)
 {
-       if (srv_encryption_on()) {
-               uint16_t enc_num;
-               NTSTATUS status = get_enc_ctx_num(inbuf, &enc_num);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return false;
-               }
-               return (enc_num == 0);
+       if (is_encrypted_packet(inbuf)) {
+               return true;
        }
        return (strncmp(smb_base(inbuf),"\377SMB",4) == 0);
 }
@@ -162,7 +192,7 @@ static ssize_t read_packet_remainder(int fd,
                                (2*14) + /* word count (including bcc) */ \
                                1 /* pad byte */)
 
-ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
+static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
                                        const char lenbuf[4],
                                        int fd,
                                        char **buffer,
@@ -202,7 +232,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
         * valid writeX call.
         */
 
-       if (is_valid_writeX_buffer(writeX_header)) {
+       if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
                /*
                 * If the data offset is beyond what
                 * we've read, drain the extra bytes.
@@ -310,7 +340,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
                return -1;
        }
 
-       if (CVAL(lenbuf,0) != SMBkeepalive &&
+       if (CVAL(lenbuf,0) == 0 &&
                        min_recv_size &&
                        smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */
                        !srv_is_signing_active()) {
@@ -350,18 +380,24 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
        return len + 4;
 }
 
-ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
-                          unsigned int timeout, size_t *p_unread)
+static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx,
+                               int fd,
+                               char **buffer,
+                               unsigned int timeout,
+                               size_t *p_unread,
+                               bool *p_encrypted)
 {
        ssize_t len;
 
+       *p_encrypted = false;
+
        len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread);
 
        if (len < 0) {
                return -1;
        }
 
-       if (srv_encryption_on()) {
+       if (is_encrypted_packet((uint8_t *)*buffer)) {
                NTSTATUS status = srv_decrypt_buffer(*buffer);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
@@ -371,6 +407,7 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
                                        SMB_READ_BAD_DECRYPT);
                        return -1;
                }
+               *p_encrypted = true;
        }
 
        /* Check the incoming SMB signature. */
@@ -390,7 +427,8 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
 
 void init_smb_request(struct smb_request *req,
                        const uint8 *inbuf,
-                       size_t unread_bytes)
+                       size_t unread_bytes,
+                       bool encrypted)
 {
        size_t req_size = smb_len(inbuf) + 4;
        /* Ensure we have at least smb_size bytes. */
@@ -406,6 +444,8 @@ void init_smb_request(struct smb_request *req,
        req->tid    = SVAL(inbuf, smb_tid);
        req->wct    = CVAL(inbuf, smb_wct);
        req->unread_bytes = unread_bytes;
+       req->encrypted = encrypted;
+       req->conn = conn_find(req->tid);
 
        /* Ensure we have at least wct words and 2 bytes of bcc. */
        if (smb_size + req->wct*2 > req_size) {
@@ -463,6 +503,7 @@ static bool push_queued_message(struct smb_request *req,
 
        msg->request_time = request_time;
        msg->end_time = end_time;
+       msg->encrypted = req->encrypted;
 
        if (private_data) {
                msg->private_data = data_blob_talloc(msg, private_data,
@@ -738,7 +779,8 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx,
                                char **buffer,
                                size_t *buffer_len,
                                int timeout,
-                               size_t *p_unread)
+                               size_t *p_unread,
+                               bool *p_encrypted)
 {
        fd_set r_fds, w_fds;
        int selrtn;
@@ -805,6 +847,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx,
                                return False;
                        }
                        *buffer_len = msg->buf.length;
+                       *p_encrypted = msg->encrypted;
 
                        /* We leave this message on the queue so the open code can
                           know this is a retry. */
@@ -921,7 +964,8 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx,
                goto again;
        }
 
-       len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, p_unread);
+       len = receive_smb_talloc(mem_ctx, smbd_server_fd(),
+                               buffer, 0, p_unread, p_encrypted);
 
        if (len == -1) {
                return False;
@@ -1288,8 +1332,7 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
        }
 
        construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
-       srv_set_message((const char *)req->inbuf,
-                       (char *)req->outbuf, num_words, num_bytes, false);
+       srv_set_message((char *)req->outbuf, num_words, num_bytes, false);
        /*
         * Zero out the word area, the caller has to take care of the bcc area
         * himself
@@ -1347,11 +1390,11 @@ static void smb_dump(const char *name, int type, const char *data, ssize_t len)
  find.
 ****************************************************************************/
 
-static void switch_message(uint8 type, struct smb_request *req, int size)
+static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
 {
        int flags;
        uint16 session_tag;
-       connection_struct *conn;
+       connection_struct *conn = NULL;
 
        static uint16 last_session_tag = UID_FIELD_INVALID;
 
@@ -1359,7 +1402,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
 
        /* Make sure this is an SMB packet. smb_size contains NetBIOS header
         * so subtract 4 from it. */
-       if (!valid_smb_header((const char *)req->inbuf)
+       if (!valid_smb_header(req->inbuf)
            || (size < (smb_size - 4))) {
                DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
                         smb_len(req->inbuf)));
@@ -1370,7 +1413,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
                DEBUG(0,("Unknown message type %d!\n",type));
                smb_dump("Unknown", 1, (char *)req->inbuf, size);
                reply_unknown_new(req, type);
-               return;
+               return NULL;
        }
 
        flags = smb_messages[type].flags;
@@ -1378,7 +1421,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
        /* In share mode security we must ignore the vuid. */
        session_tag = (lp_security() == SEC_SHARE)
                ? UID_FIELD_INVALID : req->vuid;
-       conn = conn_find(req->tid);
+       conn = req->conn;
 
        DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
                 (int)sys_getpid(), (unsigned long)conn));
@@ -1423,12 +1466,12 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
                        } else {
                                reply_doserror(req, ERRSRV, ERRinvnid);
                        }
-                       return;
+                       return NULL;
                }
 
                if (!change_to_user(conn,session_tag)) {
                        reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
-                       return;
+                       return conn;
                }
 
                /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
@@ -1436,13 +1479,13 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
                /* Does it need write permission? */
                if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
                        reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
-                       return;
+                       return conn;
                }
 
                /* IPC services are limited */
                if (IS_IPC(conn) && !(flags & CAN_IPC)) {
                        reply_doserror(req, ERRSRV,ERRaccess);
-                       return;
+                       return conn;
                }
        } else {
                /* This call needs to be run as root */
@@ -1451,21 +1494,24 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
 
        /* load service specific parameters */
        if (conn) {
+               if (req->encrypted) {
+                       conn->encrypted_tid = true;
+                       /* encrypted required from now on. */
+                       conn->encrypt_level = Required;
+               } else if (ENCRYPTION_REQUIRED(conn)) {
+                       uint8 com = CVAL(req->inbuf,smb_com);
+                       if (com != SMBtrans2 && com != SMBtranss2) {
+                               exit_server_cleanly("encryption required "
+                                       "on connection");
+                               return conn;
+                       }
+               }
+
                if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
                                         (flags & (AS_USER|DO_CHDIR)
                                          ?True:False))) {
                        reply_doserror(req, ERRSRV, ERRaccess);
-                       return;
-               }
-
-               if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
-                       /* An encrypted packet has 0xFF 'E' at offset 4
-                        * which is little endian 0x45FF */
-                       uint8 com = CVAL(req->inbuf,smb_com);
-                       if (com != SMBtrans2 && com != SMBtranss2) {
-                               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-                               return;
-                       }
+                       return conn;
                }
                conn->num_smb_operations++;
        }
@@ -1476,19 +1522,21 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
                !check_access(smbd_server_fd(), lp_hostsallow(-1),
                              lp_hostsdeny(-1)))) {
                reply_doserror(req, ERRSRV, ERRaccess);
-               return;
+               return conn;
        }
 
        smb_messages[type].fn_new(conn, req);
+       return req->conn;
 }
 
 /****************************************************************************
  Construct a reply to the incoming packet.
 ****************************************************************************/
 
-static void construct_reply(char *inbuf, int size, size_t unread_bytes)
+static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
 {
        uint8 type = CVAL(inbuf,smb_com);
+       connection_struct *conn;
        struct smb_request *req;
 
        chain_size = 0;
@@ -1498,9 +1546,9 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes)
        if (!(req = talloc(talloc_tos(), struct smb_request))) {
                smb_panic("could not allocate smb_request");
        }
-       init_smb_request(req, (uint8 *)inbuf, unread_bytes);
+       init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
 
-       switch_message(type, req, size);
+       conn = switch_message(type, req, size);
 
        if (req->unread_bytes) {
                /* writeX failed. drain socket. */
@@ -1519,8 +1567,10 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes)
                show_msg((char *)req->outbuf);
        }
 
-       if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) {
-               exit_server_cleanly("construct_reply: send_smb failed.");
+       if (!srv_send_smb(smbd_server_fd(),
+                       (char *)req->outbuf,
+                       IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
+               exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
 
        TALLOC_FREE(req);
@@ -1532,7 +1582,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes)
  Process an smb from the client
 ****************************************************************************/
 
-static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
+static void process_smb(char *inbuf, size_t nread, size_t unread_bytes, bool encrypted)
 {
        static int trans_num;
        int msg_type = CVAL(inbuf,0);
@@ -1553,7 +1603,7 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
                        static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
                        DEBUG( 1, ( "Connection denied from %s\n",
                                client_addr(get_client_fd(),addr,sizeof(addr)) ) );
-                       (void)send_smb(smbd_server_fd(),(char *)buf);
+                       (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
                        exit_server_cleanly("connection denied");
                }
        }
@@ -1574,7 +1624,7 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
 
        show_msg(inbuf);
 
-       construct_reply(inbuf,nread,unread_bytes);
+       construct_reply(inbuf,nread,unread_bytes,encrypted);
 
        trans_num++;
 }
@@ -1611,7 +1661,7 @@ void remove_from_common_flags2(uint32 v)
 
 void construct_reply_common(const char *inbuf, char *outbuf)
 {
-       srv_set_message(inbuf,outbuf,0,0,false);
+       srv_set_message(outbuf,0,0,false);
        
        SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
        SIVAL(outbuf,smb_rcls,0);
@@ -1734,7 +1784,7 @@ void chain_reply(struct smb_request *req)
        if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
                smb_panic("could not allocate smb_request");
        }
-       init_smb_request(req2, (uint8 *)inbuf2,0);
+       init_smb_request(req2, (uint8 *)inbuf2,0, req->encrypted);
 
        /* process the request */
        switch_message(smb_com2, req2, new_size);
@@ -2020,6 +2070,7 @@ void smbd_process(void)
                int num_echos;
                char *inbuf;
                size_t inbuf_len;
+               bool encrypted = false;
                TALLOC_CTX *frame = talloc_stackframe();
 
                errno = 0;
@@ -2035,7 +2086,9 @@ void smbd_process(void)
                run_events(smbd_event_context(), 0, NULL, NULL);
 
                while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
-                                              select_timeout, &unread_bytes)) {
+                                               select_timeout,
+                                               &unread_bytes,
+                                               &encrypted)) {
                        if(!timeout_processing(&select_timeout,
                                               &last_timeout_processing_time))
                                return;
@@ -2054,7 +2107,7 @@ void smbd_process(void)
                 */
                num_echos = smb_echo_count;
 
-               process_smb(inbuf, inbuf_len, unread_bytes);
+               process_smb(inbuf, inbuf_len, unread_bytes, encrypted);
 
                TALLOC_FREE(inbuf);
 
index c859efd370282e9c6ed7d637ebdf3aaaf2d0a363..b6efccdb158ce0de0c02f0bb996f92c980cbc3f8 100644 (file)
@@ -391,7 +391,7 @@ void reply_special(char *inbuf)
 
        /*
         * We only really use 4 bytes of the outbuf, but for the smb_setlen
-        * calculation & friends (send_smb uses that) we need the full smb
+        * calculation & friends (srv_send_smb uses that) we need the full smb
         * header.
         */
        char outbuf[smb_size];
@@ -470,7 +470,7 @@ void reply_special(char *inbuf)
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
 
-       send_smb(smbd_server_fd(), outbuf);
+       srv_send_smb(smbd_server_fd(), outbuf, false);
        return;
 }
 
@@ -523,6 +523,7 @@ void reply_tcon(connection_struct *conn, struct smb_request *req)
        password_blob = data_blob(password, pwlen+1);
 
        conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
+       req->conn = conn;
 
        data_blob_clear_free(&password_blob);
 
@@ -578,6 +579,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
        /* we might have to close an old one */
        if ((tcon_flags & 0x1) && conn) {
                close_cnum(conn,req->vuid);
+               req->conn = NULL;
        }
 
        if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
@@ -646,6 +648,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
 
        conn = make_connection(service, password, client_devicetype,
                               req->vuid, &nt_status);
+       req->conn =conn;
 
        data_blob_clear_free(&password);
 
@@ -2725,7 +2728,7 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req)
 
        START_PROFILE(SMBreadbraw);
 
-       if (srv_is_signing_active() || srv_encryption_on()) {
+       if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
                exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
                        "raw reads/writes are disallowed.");
        }
@@ -2951,8 +2954,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                return;
        }
        
-       srv_set_message((const char *)req->inbuf,
-               (char *)req->outbuf, 5, nread+3, False);
+       srv_set_message((char *)req->outbuf, 5, nread+3, False);
 
        SSVAL(req->outbuf,smb_vwv0,nread);
        SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -3039,8 +3041,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                return;
        }
 
-       srv_set_message((const char *)req->inbuf,
-               (char *)req->outbuf, 5, nread+3, False);
+       srv_set_message((char *)req->outbuf, 5, nread+3, False);
 
        SSVAL(req->outbuf,smb_vwv0,nread);
        SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -3058,12 +3059,12 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
  Setup readX header.
 ****************************************************************************/
 
-static int setup_readX_header(const char *inbuf, char *outbuf, size_t smb_maxcnt)
+static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
 {
        int outsize;
        char *data;
 
-       outsize = srv_set_message(inbuf, outbuf,12,smb_maxcnt,False);
+       outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
        data = smb_buf(outbuf);
 
        memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
@@ -3113,6 +3114,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
         */
 
        if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
+           !is_encrypted_packet(req->inbuf) &&
            lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
                uint8 headerbuf[smb_size + 12 * 2];
                DATA_BLOB header;
@@ -3126,8 +3128,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                header = data_blob_const(headerbuf, sizeof(headerbuf));
 
                construct_reply_common((char *)req->inbuf, (char *)headerbuf);
-               setup_readX_header((const char *)req->inbuf,
-                       (char *)headerbuf, smb_maxcnt);
+               setup_readX_header((char *)headerbuf, smb_maxcnt);
 
                if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
                        /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
@@ -3178,8 +3179,7 @@ normal_read:
                uint8 headerbuf[smb_size + 2*12];
 
                construct_reply_common((char *)req->inbuf, (char *)headerbuf);
-               setup_readX_header((const char *)req->inbuf,
-                       (char *)headerbuf, smb_maxcnt);
+               setup_readX_header((char *)headerbuf, smb_maxcnt);
 
                /* Send out the header. */
                if (write_data(smbd_server_fd(), (char *)headerbuf,
@@ -3206,8 +3206,7 @@ normal_read:
                        return;
                }
 
-               setup_readX_header((const char *)req->inbuf,
-                       (char *)req->outbuf, nread);
+               setup_readX_header((char *)req->outbuf, nread);
 
                DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
                        fsp->fnum, (int)smb_maxcnt, (int)nread ) );
@@ -3272,7 +3271,7 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req)
                                return;
                        }
                        /* We currently don't do this on signed or sealed data. */
-                       if (srv_is_signing_active() || srv_encryption_on()) {
+                       if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
                                reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
                                END_PROFILE(SMBreadX);
                                return;
@@ -3463,13 +3462,15 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
         * it to send more bytes */
 
        memcpy(buf, req->inbuf, smb_size);
-       outsize = srv_set_message((const char *)req->inbuf, buf,
+       outsize = srv_set_message(buf,
                        Protocol>PROTOCOL_COREPLUS?1:0,0,True);
        SCVAL(buf,smb_com,SMBwritebraw);
        SSVALS(buf,smb_vwv0,0xFFFF);
        show_msg(buf);
-       if (!send_smb(smbd_server_fd(),buf)) {
-               exit_server_cleanly("reply_writebraw: send_smb "
+       if (!srv_send_smb(smbd_server_fd(),
+                       buf,
+                       IS_CONN_ENCRYPTED(conn))) {
+               exit_server_cleanly("reply_writebraw: srv_send_smb "
                        "failed.");
        }
 
@@ -3788,14 +3789,14 @@ void reply_write(connection_struct *conn, struct smb_request *req)
                                                (2*14) + /* word count (including bcc) */ \
                                                1 /* pad byte */)
 
-bool is_valid_writeX_buffer(const char *inbuf)
+bool is_valid_writeX_buffer(const uint8_t *inbuf)
 {
        size_t numtowrite;
        connection_struct *conn = NULL;
        unsigned int doff = 0;
        size_t len = smb_len_large(inbuf);
 
-       if (srv_encryption_on()) {
+       if (is_encrypted_packet(inbuf)) {
                /* Can't do this on encrypted
                 * connections. */
                return false;
@@ -4476,6 +4477,7 @@ void reply_tdis(connection_struct *conn, struct smb_request *req)
        conn->used = False;
 
        close_cnum(conn,req->vuid);
+       req->conn = NULL;
 
        reply_outbuf(req, 0, 0);
        END_PROFILE(SMBtdis);
@@ -4526,8 +4528,10 @@ void reply_echo(connection_struct *conn, struct smb_request *req)
                SSVAL(req->outbuf,smb_vwv0,seq_num);
 
                show_msg((char *)req->outbuf);
-               if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
-                       exit_server_cleanly("reply_echo: send_smb failed.");
+               if (!srv_send_smb(smbd_server_fd(),
+                               (char *)req->outbuf,
+                               IS_CONN_ENCRYPTED(conn)||req->encrypted))
+                       exit_server_cleanly("reply_echo: srv_send_smb failed.");
        }
 
        DEBUG(3,("echo %d times\n", smb_reverb));
@@ -4830,7 +4834,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = create_directory(conn, directory);
+       status = create_directory(conn, req, directory);
 
        DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
 
@@ -6803,8 +6807,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req)
                                 * onto the blocking lock queue.
                                 */
                                if(push_blocking_lock_request(br_lck,
-                                                       (char *)req->inbuf,
-                                                       smb_len(req->inbuf)+4,
+                                                       req,
                                                        fsp,
                                                        lock_timeout,
                                                        i,
index 24ecb77fd5985515643a9109458785a637e24035..21fca73feaede3c3e5fbe795264ad5dd17e791f5 100644 (file)
@@ -36,24 +36,37 @@ static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx;
 static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx;
 
 /******************************************************************************
- Is server encryption on ?
+ Return global enc context - this must change if we ever do multiple contexts.
 ******************************************************************************/
 
-bool srv_encryption_on(void)
+uint16_t srv_enc_ctx(void)
 {
-       if (srv_trans_enc_ctx) {
-               return common_encryption_on(srv_trans_enc_ctx->es);
-       }
-       return false;
+       return srv_trans_enc_ctx->es->enc_ctx_num;
 }
 
 /******************************************************************************
- Return global enc context - this must change if we ever do multiple contexts.
+ Is this an incoming encrypted packet ?
 ******************************************************************************/
 
-uint16 srv_enc_ctx(void)
+bool is_encrypted_packet(const uint8_t *inbuf)
 {
-       return srv_trans_enc_ctx->es->enc_ctx_num;
+       NTSTATUS status;
+       uint16_t enc_num;
+
+       /* Ignore non-session messages. */
+       if(CVAL(inbuf,0)) {
+               return false;
+       }
+
+       status = get_enc_ctx_num(inbuf, &enc_num);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) {
+               return true;
+       }
+       return false;
 }
 
 /******************************************************************************
@@ -292,9 +305,9 @@ void srv_free_enc_buffer(char *buf)
 {
        /* We know this is an smb buffer, and we
         * didn't malloc, only copy, for a keepalive,
-        * so ignore session keepalives. */
+        * so ignore non-session messages. */
 
-       if(CVAL(buf,0) == SMBkeepalive) {
+       if(CVAL(buf,0)) {
                return;
        }
 
@@ -309,8 +322,8 @@ void srv_free_enc_buffer(char *buf)
 
 NTSTATUS srv_decrypt_buffer(char *buf)
 {
-       /* Ignore session keepalives. */
-       if(CVAL(buf,0) == SMBkeepalive) {
+       /* Ignore non-session messages. */
+       if(CVAL(buf,0)) {
                return NT_STATUS_OK;
        }
 
@@ -329,8 +342,8 @@ NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out)
 {
        *buf_out = buf;
 
-       /* Ignore session keepalives. */
-       if(CVAL(buf,0) == SMBkeepalive) {
+       /* Ignore non-session messages. */
+       if(CVAL(buf,0)) {
                return NT_STATUS_OK;
        }
 
@@ -698,6 +711,7 @@ NTSTATUS srv_encryption_start(connection_struct *conn)
        srv_trans_enc_ctx->es->enc_on = true;
 
        partial_srv_trans_enc_ctx = NULL;
+
        return NT_STATUS_OK;
 }
 
index 8ca012ff248f6dacb032d85edbbfa80dc6822d2b..e44a540554b6284e491e01f91478c709ffdc2beb 100644 (file)
@@ -139,7 +139,7 @@ static void reply_sesssetup_blob(connection_struct *conn,
        }
 
        show_msg((char *)req->outbuf);
-       send_smb(smbd_server_fd(),(char *)req->outbuf);
+       srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
        TALLOC_FREE(req->outbuf);
 }
 
index eba8cb50f0443db5c277ee9ea371ec26e9fb1bc1..1e421a70b64700f65c05f62817709a6921daf3b7 100644 (file)
@@ -575,7 +575,8 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
   HACK ! Always assumes smb_setup field is zero.
 ****************************************************************************/
 
-void send_trans2_replies(struct smb_request *req,
+void send_trans2_replies(connection_struct *conn,
+                       struct smb_request *req,
                         const char *params,
                         int paramsize,
                         const char *pdata,
@@ -737,8 +738,10 @@ void send_trans2_replies(struct smb_request *req,
 
                /* Send the packet */
                show_msg((char *)req->outbuf);
-               if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
-                       exit_server_cleanly("send_trans2_replies: send_smb failed.");
+               if (!srv_send_smb(smbd_server_fd(),
+                               (char *)req->outbuf,
+                               IS_CONN_ENCRYPTED(conn)))
+                       exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
 
                TALLOC_FREE(req->outbuf);
 
@@ -956,7 +959,7 @@ static void call_trans2open(connection_struct *conn,
        }
 
        /* Send the required number of replies */
-       send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
 }
 
 /*********************************************************
@@ -2026,7 +2029,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        SSVAL(params,6,0); /* Never an EA error */
        SSVAL(params,8,last_entry_off);
 
-       send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
+       send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
                            max_data_bytes);
 
        if ((! *directory) && dptr_path(dptr_num)) {
@@ -2350,7 +2353,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        SSVAL(params,4,0); /* Never an EA error */
        SSVAL(params,6,last_entry_off);
 
-       send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
+       send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
                            max_data_bytes);
 
        return;
@@ -2389,13 +2392,23 @@ static void call_trans2qfsinfo(connection_struct *conn,
 
        info_level = SVAL(params,0);
 
-       if (IS_IPC(conn) || 
-                       (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF )) {
+       if (IS_IPC(conn)) {
+               if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+                       DEBUG(0,("call_trans2qfsinfo: not an allowed "
+                               "info level (0x%x) on IPC$.\n",
+                               (unsigned int)info_level));
+                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
+               }
+       }
+
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
                if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
                        DEBUG(0,("call_trans2qfsinfo: encryption required "
                                "and info level 0x%x sent.\n",
                                (unsigned int)info_level));
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       exit_server_cleanly("encryption required "
+                               "on connection");
                        return;
                }
        }
@@ -2906,7 +2919,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
        }
 
 
-       send_trans2_replies(req, params, 0, pdata, data_len,
+       send_trans2_replies(conn, req, params, 0, pdata, data_len,
                            max_data_bytes);
 
        DEBUG( 4, ( "%s info_level = %d\n",
@@ -2952,12 +2965,13 @@ static void call_trans2setfsinfo(connection_struct *conn,
                }
        }
 
-       if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
+       if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
                if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
                        DEBUG(0,("call_trans2setfsinfo: encryption required "
                                "and info level 0x%x sent.\n",
                                (unsigned int)info_level));
-                       reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       exit_server_cleanly("encryption required "
+                               "on connection");
                        return;
                }
        }
@@ -3048,7 +3062,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                        return;
                                }
 
-                               send_trans2_replies(req,
+                               send_trans2_replies(conn, req,
                                                *pparams,
                                                param_len,
                                                *ppdata,
@@ -3524,7 +3538,7 @@ static void call_trans2qpipeinfo(connection_struct *conn,
                        return;
        }
 
-       send_trans2_replies(req, params, param_size, *ppdata, data_size,
+       send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
                            max_data_bytes);
 
        return;
@@ -4456,7 +4470,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        return;
        }
 
-       send_trans2_replies(req, params, param_size, *ppdata, data_size,
+       send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
                            max_data_bytes);
 
        return;
@@ -5160,8 +5174,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
-                               const uint8 *inbuf,
-                               int length,
+                               const struct smb_request *req,
                                const char *pdata,
                                int total_data,
                                files_struct *fsp)
@@ -5171,6 +5184,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
        uint32 lock_pid;
        bool blocking_lock = False;
        enum brl_type lock_type;
+
        NTSTATUS status = NT_STATUS_OK;
 
        if (fsp == NULL || fsp->fh->fd == -1) {
@@ -5258,7 +5272,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
                         * onto the blocking lock queue.
                         */
                        if(push_blocking_lock_request(br_lck,
-                                               (char *)inbuf, length,
+                                               req,
                                                fsp,
                                                -1, /* infinite timeout. */
                                                0,
@@ -6316,7 +6330,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
 
                                SSVAL(params,0,0);
-                               send_trans2_replies(req, params, 2,
+                               send_trans2_replies(conn, req, params, 2,
                                                    *ppdata, 0,
                                                    max_data_bytes);
                                return;
@@ -6606,8 +6620,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
                                return;
                        }
-                       status = smb_set_posix_lock(conn, req->inbuf,
-                                                   smb_len(req->inbuf) + 4,
+                       status = smb_set_posix_lock(conn, req,
                                                    pdata, total_data, fsp);
                        break;
                }
@@ -6675,7 +6688,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
        }
 
        SSVAL(params,0,0);
-       send_trans2_replies(req, params, 2, *ppdata, data_return_size,
+       send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
                            max_data_bytes);
   
        return;
@@ -6767,7 +6780,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
                return;
        }
 
-       status = create_directory(conn, directory);
+       status = create_directory(conn, req, directory);
 
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -6793,7 +6806,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
 
        SSVAL(params,0,0);
 
-       send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
   
        return;
 }
@@ -6847,7 +6860,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn,
        if(fnf_handle == 0)
                fnf_handle = 257;
 
-       send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
   
        return;
 }
@@ -6878,7 +6891,7 @@ static void call_trans2findnotifynext(connection_struct *conn,
        SSVAL(params,0,0); /* No changes */
        SSVAL(params,2,0); /* No EA errors */
 
-       send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
   
        return;
 }
@@ -6928,7 +6941,7 @@ static void call_trans2getdfsreferral(connection_struct *conn,
 
        SSVAL(req->inbuf, smb_flg2,
              SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
-       send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
+       send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
 
        return;
 }
@@ -6975,7 +6988,7 @@ static void call_trans2ioctl(connection_struct *conn,
                srvstr_push(pdata, req->flags2, pdata+18,
                            lp_servicename(SNUM(conn)), 13,
                            STR_ASCII|STR_TERMINATE); /* Service name */
-               send_trans2_replies(req, *pparams, 0, *ppdata, 32,
+               send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
                                    max_data_bytes);
                return;
        }
index 912d575c601d7c620ed51f42e40d15768142f9f4..fb01e7f9a124cd89b0cb1208bf889c00802b56ca 100644 (file)
@@ -114,6 +114,30 @@ static void filter_request(char *buf)
 
 }
 
+/****************************************************************************
+ Send an smb to a fd.
+****************************************************************************/
+
+static bool send_smb(int fd, char *buffer)
+{
+       size_t len;
+       size_t nwritten=0;
+       ssize_t ret;
+
+        len = smb_len(buffer) + 4;
+
+       while (nwritten < len) {
+               ret = write_data(fd,buffer+nwritten,len - nwritten);
+               if (ret <= 0) {
+                       DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+                               (int)len,(int)ret, strerror(errno) ));
+                       return false;
+               }
+               nwritten += ret;
+       }
+
+       return true;
+}
 
 static void filter_child(int c, struct sockaddr_storage *dest_ss)
 {
@@ -145,7 +169,7 @@ static void filter_child(int c, struct sockaddr_storage *dest_ss)
                if (num <= 0) continue;
                
                if (c != -1 && FD_ISSET(c, &fds)) {
-                       if (!receive_smb(c, packet, 0, NULL)) {
+                       if (!receive_smb_raw(c, packet, 0, NULL)) {
                                d_printf("client closed connection\n");
                                exit(0);
                        }
@@ -156,7 +180,7 @@ static void filter_child(int c, struct sockaddr_storage *dest_ss)
                        }                       
                }
                if (s != -1 && FD_ISSET(s, &fds)) {
-                       if (!receive_smb(s, packet, 0, NULL)) {
+                       if (!receive_smb_raw(s, packet, 0, NULL)) {
                                d_printf("server closed connection\n");
                                exit(0);
                        }