smbd: Move send_trans2_replies to smb1_trans2.c
authorDavid Mulder <dmulder@suse.com>
Mon, 21 Mar 2022 17:51:41 +0000 (11:51 -0600)
committerJeremy Allison <jra@samba.org>
Thu, 7 Apr 2022 17:37:30 +0000 (17:37 +0000)
Signed-off-by: David Mulder <dmulder@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/proto.h
source3/smbd/smb1_trans2.c [new file with mode: 0644]
source3/smbd/smb1_trans2.h [new file with mode: 0644]
source3/smbd/smbd.h
source3/smbd/trans2.c
source3/wscript_build

index 7fb1a46136880db16d948134eb2c775988b3f670..e63e72e5ffebba4222d16bcea85500bf21ae4390 100644 (file)
@@ -1096,14 +1096,6 @@ NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
                        size_t *pnum_names);
 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                struct ea_list *ea_list);
-void send_trans2_replies(connection_struct *conn,
-                       struct smb_request *req,
-                       NTSTATUS status,
-                        const char *params,
-                        int paramsize,
-                        const char *pdata,
-                        int datasize,
-                        int max_data_bytes);
 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16]);
 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
                connection_struct *conn,
diff --git a/source3/smbd/smb1_trans2.c b/source3/smbd/smb1_trans2.c
new file mode 100644 (file)
index 0000000..619cec0
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+   Unix SMB/CIFS implementation.
+   SMB transaction2 handling
+   Copyright (C) Jeremy Allison                        1994-2007
+   Copyright (C) Stefan (metze) Metzmacher     2003
+   Copyright (C) Volker Lendecke               2005-2007
+   Copyright (C) Steve French                  2005
+   Copyright (C) James Peach                   2006-2007
+
+   Extensively modified by Andrew Tridgell, 1995
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "ntioctl.h"
+#include "system/filesys.h"
+#include "lib/util/time_basic.h"
+#include "version.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "../librpc/gen_ndr/xattr.h"
+#include "../librpc/gen_ndr/ndr_security.h"
+#include "libcli/security/security.h"
+#include "trans2.h"
+#include "auth.h"
+#include "smbprofile.h"
+#include "rpc_server/srv_pipe_hnd.h"
+#include "printing.h"
+#include "lib/util_ea.h"
+#include "lib/readdir_attr.h"
+#include "messages.h"
+#include "libcli/smb/smb2_posix.h"
+#include "lib/util/string_wrappers.h"
+#include "source3/lib/substitute.h"
+#include "source3/lib/adouble.h"
+
+/****************************************************************************
+  Send the required number of replies back.
+  We assume all fields other than the data fields are
+  set correctly for the type of call.
+  HACK ! Always assumes smb_setup field is zero.
+****************************************************************************/
+
+void send_trans2_replies(connection_struct *conn,
+                       struct smb_request *req,
+                       NTSTATUS status,
+                        const char *params,
+                        int paramsize,
+                        const char *pdata,
+                        int datasize,
+                        int max_data_bytes)
+{
+       /* As we are using a protocol > LANMAN1 then the max_send
+        variable must have been set in the sessetupX call.
+        This takes precedence over the max_xmit field in the
+        global struct. These different max_xmit variables should
+        be merged as this is now too confusing */
+
+       int data_to_send = datasize;
+       int params_to_send = paramsize;
+       int useable_space;
+       const char *pp = params;
+       const char *pd = pdata;
+       int params_sent_thistime, data_sent_thistime, total_sent_thistime;
+       int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
+       int data_alignment_offset = 0;
+       bool overflow = False;
+       struct smbXsrv_connection *xconn = req->xconn;
+       int max_send = xconn->smb1.sessions.max_send;
+
+       /* Modify the data_to_send and datasize and set the error if
+          we're trying to send more than max_data_bytes. We still send
+          the part of the packet(s) that fit. Strange, but needed
+          for OS/2. */
+
+       if (max_data_bytes > 0 && datasize > max_data_bytes) {
+               DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
+                       max_data_bytes, datasize ));
+               datasize = data_to_send = max_data_bytes;
+               overflow = True;
+       }
+
+       /* If there genuinely are no parameters or data to send just send the empty packet */
+
+       if(params_to_send == 0 && data_to_send == 0) {
+               reply_outbuf(req, 10, 0);
+               if (NT_STATUS_V(status)) {
+                       uint8_t eclass;
+                       uint32_t ecode;
+                       ntstatus_to_dos(status, &eclass, &ecode);
+                       error_packet_set((char *)req->outbuf,
+                                       eclass, ecode, status,
+                                       __LINE__,__FILE__);
+               }
+               show_msg((char *)req->outbuf);
+               if (!srv_send_smb(xconn,
+                               (char *)req->outbuf,
+                               true, req->seqnum+1,
+                               IS_CONN_ENCRYPTED(conn),
+                               &req->pcd)) {
+                       exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
+               }
+               TALLOC_FREE(req->outbuf);
+               return;
+       }
+
+       /* When sending params and data ensure that both are nicely aligned */
+       /* Only do this alignment when there is also data to send - else
+               can cause NT redirector problems. */
+
+       if (((params_to_send % 4) != 0) && (data_to_send != 0))
+               data_alignment_offset = 4 - (params_to_send % 4);
+
+       /* Space is bufsize minus Netbios over TCP header minus SMB header */
+       /* The alignment_offset is to align the param bytes on an even byte
+               boundary. NT 4.0 Beta needs this to work correctly. */
+
+       useable_space = max_send - (smb_size
+                                   + 2 * 10 /* wct */
+                                   + alignment_offset
+                                   + data_alignment_offset);
+
+       if (useable_space < 0) {
+               DEBUG(0, ("send_trans2_replies failed sanity useable_space "
+                         "= %d!!!", useable_space));
+               exit_server_cleanly("send_trans2_replies: Not enough space");
+       }
+
+       while (params_to_send || data_to_send) {
+               /* Calculate whether we will totally or partially fill this packet */
+
+               total_sent_thistime = params_to_send + data_to_send;
+
+               /* We can never send more than useable_space */
+               /*
+                * Note that 'useable_space' does not include the alignment offsets,
+                * but we must include the alignment offsets in the calculation of
+                * the length of the data we send over the wire, as the alignment offsets
+                * are sent here. Fix from Marc_Jacobsen@hp.com.
+                */
+
+               total_sent_thistime = MIN(total_sent_thistime, useable_space);
+
+               reply_outbuf(req, 10, total_sent_thistime + alignment_offset
+                            + data_alignment_offset);
+
+               /* Set total params and data to be sent */
+               SSVAL(req->outbuf,smb_tprcnt,paramsize);
+               SSVAL(req->outbuf,smb_tdrcnt,datasize);
+
+               /* Calculate how many parameters and data we can fit into
+                * this packet. Parameters get precedence
+                */
+
+               params_sent_thistime = MIN(params_to_send,useable_space);
+               data_sent_thistime = useable_space - params_sent_thistime;
+               data_sent_thistime = MIN(data_sent_thistime,data_to_send);
+
+               SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
+
+               /* smb_proff is the offset from the start of the SMB header to the
+                       parameter bytes, however the first 4 bytes of outbuf are
+                       the Netbios over TCP header. Thus use smb_base() to subtract
+                       them from the calculation */
+
+               SSVAL(req->outbuf,smb_proff,
+                     ((smb_buf(req->outbuf)+alignment_offset)
+                      - smb_base(req->outbuf)));
+
+               if(params_sent_thistime == 0)
+                       SSVAL(req->outbuf,smb_prdisp,0);
+               else
+                       /* Absolute displacement of param bytes sent in this packet */
+                       SSVAL(req->outbuf,smb_prdisp,pp - params);
+
+               SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
+               if(data_sent_thistime == 0) {
+                       SSVAL(req->outbuf,smb_droff,0);
+                       SSVAL(req->outbuf,smb_drdisp, 0);
+               } else {
+                       /* The offset of the data bytes is the offset of the
+                               parameter bytes plus the number of parameters being sent this time */
+                       SSVAL(req->outbuf, smb_droff,
+                             ((smb_buf(req->outbuf)+alignment_offset)
+                              - smb_base(req->outbuf))
+                             + params_sent_thistime + data_alignment_offset);
+                       SSVAL(req->outbuf,smb_drdisp, pd - pdata);
+               }
+
+               /* Initialize the padding for alignment */
+
+               if (alignment_offset != 0) {
+                       memset(smb_buf(req->outbuf), 0, alignment_offset);
+               }
+
+               /* Copy the param bytes into the packet */
+
+               if(params_sent_thistime) {
+                       memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
+                              params_sent_thistime);
+               }
+
+               /* Copy in the data bytes */
+               if(data_sent_thistime) {
+                       if (data_alignment_offset != 0) {
+                               memset((smb_buf(req->outbuf)+alignment_offset+
+                                       params_sent_thistime), 0,
+                                      data_alignment_offset);
+                       }
+                       memcpy(smb_buf(req->outbuf)+alignment_offset
+                              +params_sent_thistime+data_alignment_offset,
+                              pd,data_sent_thistime);
+               }
+
+               DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
+                       params_sent_thistime, data_sent_thistime, useable_space));
+               DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
+                       params_to_send, data_to_send, paramsize, datasize));
+
+               if (overflow) {
+                       error_packet_set((char *)req->outbuf,
+                                        ERRDOS,ERRbufferoverflow,
+                                        STATUS_BUFFER_OVERFLOW,
+                                        __LINE__,__FILE__);
+               } else if (NT_STATUS_V(status)) {
+                       uint8_t eclass;
+                       uint32_t ecode;
+                       ntstatus_to_dos(status, &eclass, &ecode);
+                       error_packet_set((char *)req->outbuf,
+                                       eclass, ecode, status,
+                                       __LINE__,__FILE__);
+               }
+
+               /* Send the packet */
+               show_msg((char *)req->outbuf);
+               if (!srv_send_smb(xconn,
+                               (char *)req->outbuf,
+                               true, req->seqnum+1,
+                               IS_CONN_ENCRYPTED(conn),
+                               &req->pcd))
+                       exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
+
+               TALLOC_FREE(req->outbuf);
+
+               pp += params_sent_thistime;
+               pd += data_sent_thistime;
+
+               params_to_send -= params_sent_thistime;
+               data_to_send -= data_sent_thistime;
+
+               /* Sanity check */
+               if(params_to_send < 0 || data_to_send < 0) {
+                       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
+                               params_to_send, data_to_send));
+                       return;
+               }
+       }
+
+       return;
+}
diff --git a/source3/smbd/smb1_trans2.h b/source3/smbd/smb1_trans2.h
new file mode 100644 (file)
index 0000000..6eee7ca
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+   Unix SMB/CIFS implementation.
+   SMB transaction2 handling
+   Copyright (C) Jeremy Allison                        1994-2007
+   Copyright (C) Stefan (metze) Metzmacher     2003
+   Copyright (C) Volker Lendecke               2005-2007
+   Copyright (C) Steve French                  2005
+   Copyright (C) James Peach                   2006-2007
+
+   Extensively modified by Andrew Tridgell, 1995
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+void send_trans2_replies(connection_struct *conn,
+                       struct smb_request *req,
+                       NTSTATUS status,
+                        const char *params,
+                        int paramsize,
+                        const char *pdata,
+                        int datasize,
+                        int max_data_bytes);
index 4a9cb183c7452175a12b86d2bb1dd48f413c7e84..f2c3abcda2d0ec2cd656a1e269a53b358a4e20b6 100644 (file)
@@ -41,6 +41,7 @@ struct dptr_struct;
 #include "smbd/smb1_signing.h"
 #include "smbd/smb1_process.h"
 #include "smbd/smb1_utils.h"
+#include "smbd/smb1_trans2.h"
 #endif
 
 struct trans_state {
index f24a230d940d9623b195cefb8f663ea8e3c628cd..45544141adc48578f937ef2383808169a6fbfbf8 100644 (file)
@@ -941,231 +941,6 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
        return name_list;
 }
 
-/****************************************************************************
-  Send the required number of replies back.
-  We assume all fields other than the data fields are
-  set correctly for the type of call.
-  HACK ! Always assumes smb_setup field is zero.
-****************************************************************************/
-
-void send_trans2_replies(connection_struct *conn,
-                       struct smb_request *req,
-                       NTSTATUS status,
-                        const char *params,
-                        int paramsize,
-                        const char *pdata,
-                        int datasize,
-                        int max_data_bytes)
-{
-       /* As we are using a protocol > LANMAN1 then the max_send
-        variable must have been set in the sessetupX call.
-        This takes precedence over the max_xmit field in the
-        global struct. These different max_xmit variables should
-        be merged as this is now too confusing */
-
-       int data_to_send = datasize;
-       int params_to_send = paramsize;
-       int useable_space;
-       const char *pp = params;
-       const char *pd = pdata;
-       int params_sent_thistime, data_sent_thistime, total_sent_thistime;
-       int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
-       int data_alignment_offset = 0;
-       bool overflow = False;
-       struct smbXsrv_connection *xconn = req->xconn;
-       int max_send = xconn->smb1.sessions.max_send;
-
-       /* Modify the data_to_send and datasize and set the error if
-          we're trying to send more than max_data_bytes. We still send
-          the part of the packet(s) that fit. Strange, but needed
-          for OS/2. */
-
-       if (max_data_bytes > 0 && datasize > max_data_bytes) {
-               DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
-                       max_data_bytes, datasize ));
-               datasize = data_to_send = max_data_bytes;
-               overflow = True;
-       }
-
-       /* If there genuinely are no parameters or data to send just send the empty packet */
-
-       if(params_to_send == 0 && data_to_send == 0) {
-               reply_outbuf(req, 10, 0);
-               if (NT_STATUS_V(status)) {
-                       uint8_t eclass;
-                       uint32_t ecode;
-                       ntstatus_to_dos(status, &eclass, &ecode);
-                       error_packet_set((char *)req->outbuf,
-                                       eclass, ecode, status,
-                                       __LINE__,__FILE__);
-               }
-               show_msg((char *)req->outbuf);
-               if (!srv_send_smb(xconn,
-                               (char *)req->outbuf,
-                               true, req->seqnum+1,
-                               IS_CONN_ENCRYPTED(conn),
-                               &req->pcd)) {
-                       exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
-               }
-               TALLOC_FREE(req->outbuf);
-               return;
-       }
-
-       /* When sending params and data ensure that both are nicely aligned */
-       /* Only do this alignment when there is also data to send - else
-               can cause NT redirector problems. */
-
-       if (((params_to_send % 4) != 0) && (data_to_send != 0))
-               data_alignment_offset = 4 - (params_to_send % 4);
-
-       /* Space is bufsize minus Netbios over TCP header minus SMB header */
-       /* The alignment_offset is to align the param bytes on an even byte
-               boundary. NT 4.0 Beta needs this to work correctly. */
-
-       useable_space = max_send - (smb_size
-                                   + 2 * 10 /* wct */
-                                   + alignment_offset
-                                   + data_alignment_offset);
-
-       if (useable_space < 0) {
-               DEBUG(0, ("send_trans2_replies failed sanity useable_space "
-                         "= %d!!!", useable_space));
-               exit_server_cleanly("send_trans2_replies: Not enough space");
-       }
-
-       while (params_to_send || data_to_send) {
-               /* Calculate whether we will totally or partially fill this packet */
-
-               total_sent_thistime = params_to_send + data_to_send;
-
-               /* We can never send more than useable_space */
-               /*
-                * Note that 'useable_space' does not include the alignment offsets,
-                * but we must include the alignment offsets in the calculation of
-                * the length of the data we send over the wire, as the alignment offsets
-                * are sent here. Fix from Marc_Jacobsen@hp.com.
-                */
-
-               total_sent_thistime = MIN(total_sent_thistime, useable_space);
-
-               reply_outbuf(req, 10, total_sent_thistime + alignment_offset
-                            + data_alignment_offset);
-
-               /* Set total params and data to be sent */
-               SSVAL(req->outbuf,smb_tprcnt,paramsize);
-               SSVAL(req->outbuf,smb_tdrcnt,datasize);
-
-               /* Calculate how many parameters and data we can fit into
-                * this packet. Parameters get precedence
-                */
-
-               params_sent_thistime = MIN(params_to_send,useable_space);
-               data_sent_thistime = useable_space - params_sent_thistime;
-               data_sent_thistime = MIN(data_sent_thistime,data_to_send);
-
-               SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
-
-               /* smb_proff is the offset from the start of the SMB header to the
-                       parameter bytes, however the first 4 bytes of outbuf are
-                       the Netbios over TCP header. Thus use smb_base() to subtract
-                       them from the calculation */
-
-               SSVAL(req->outbuf,smb_proff,
-                     ((smb_buf(req->outbuf)+alignment_offset)
-                      - smb_base(req->outbuf)));
-
-               if(params_sent_thistime == 0)
-                       SSVAL(req->outbuf,smb_prdisp,0);
-               else
-                       /* Absolute displacement of param bytes sent in this packet */
-                       SSVAL(req->outbuf,smb_prdisp,pp - params);
-
-               SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
-               if(data_sent_thistime == 0) {
-                       SSVAL(req->outbuf,smb_droff,0);
-                       SSVAL(req->outbuf,smb_drdisp, 0);
-               } else {
-                       /* The offset of the data bytes is the offset of the
-                               parameter bytes plus the number of parameters being sent this time */
-                       SSVAL(req->outbuf, smb_droff,
-                             ((smb_buf(req->outbuf)+alignment_offset)
-                              - smb_base(req->outbuf))
-                             + params_sent_thistime + data_alignment_offset);
-                       SSVAL(req->outbuf,smb_drdisp, pd - pdata);
-               }
-
-               /* Initialize the padding for alignment */
-
-               if (alignment_offset != 0) {
-                       memset(smb_buf(req->outbuf), 0, alignment_offset);
-               }
-
-               /* Copy the param bytes into the packet */
-
-               if(params_sent_thistime) {
-                       memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
-                              params_sent_thistime);
-               }
-
-               /* Copy in the data bytes */
-               if(data_sent_thistime) {
-                       if (data_alignment_offset != 0) {
-                               memset((smb_buf(req->outbuf)+alignment_offset+
-                                       params_sent_thistime), 0,
-                                      data_alignment_offset);
-                       }
-                       memcpy(smb_buf(req->outbuf)+alignment_offset
-                              +params_sent_thistime+data_alignment_offset,
-                              pd,data_sent_thistime);
-               }
-
-               DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
-                       params_sent_thistime, data_sent_thistime, useable_space));
-               DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
-                       params_to_send, data_to_send, paramsize, datasize));
-
-               if (overflow) {
-                       error_packet_set((char *)req->outbuf,
-                                        ERRDOS,ERRbufferoverflow,
-                                        STATUS_BUFFER_OVERFLOW,
-                                        __LINE__,__FILE__);
-               } else if (NT_STATUS_V(status)) {
-                       uint8_t eclass;
-                       uint32_t ecode;
-                       ntstatus_to_dos(status, &eclass, &ecode);
-                       error_packet_set((char *)req->outbuf,
-                                       eclass, ecode, status,
-                                       __LINE__,__FILE__);
-               }
-
-               /* Send the packet */
-               show_msg((char *)req->outbuf);
-               if (!srv_send_smb(xconn,
-                               (char *)req->outbuf,
-                               true, req->seqnum+1,
-                               IS_CONN_ENCRYPTED(conn),
-                               &req->pcd))
-                       exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
-
-               TALLOC_FREE(req->outbuf);
-
-               pp += params_sent_thistime;
-               pd += data_sent_thistime;
-
-               params_to_send -= params_sent_thistime;
-               data_to_send -= data_sent_thistime;
-
-               /* Sanity check */
-               if(params_to_send < 0 || data_to_send < 0) {
-                       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
-                               params_to_send, data_to_send));
-                       return;
-               }
-       }
-
-       return;
-}
-
 /****************************************************************************
  Reply to a TRANSACT2_OPEN.
 ****************************************************************************/
index a5448d871ff006460fad9c12f855dab428393394..e3c4eddb94d27ef8e8f312b6517153d0bdd09ced 100644 (file)
@@ -613,6 +613,7 @@ if bld.CONFIG_SET('WITH_SMB1SERVER'):
                    smbd/smb1_service.c
                    smbd/smb1_signing.c
                    smbd/smb1_process.c
+                   smbd/smb1_trans2.c
     '''
 else:
     SMB1_SOURCES = ''