smbd: Move check_path_syntax* to smb2_reply.c
authorDavid Mulder <dmulder@suse.com>
Tue, 15 Mar 2022 22:29:59 +0000 (16:29 -0600)
committerJeremy Allison <jra@samba.org>
Thu, 7 Apr 2022 17:37:29 +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/reply.c
source3/smbd/smb2_reply.c [new file with mode: 0644]
source3/wscript_build

index 3822ed64d738593754323506e59fd03f07306586..6cc980eab6f2838ed95ebfb8ba073962f3fd3356 100644 (file)
@@ -912,8 +912,6 @@ bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
 
 /* The following definitions come from smbd/reply.c  */
 
-NTSTATUS check_path_syntax(char *path);
-NTSTATUS check_path_syntax_posix(char *path);
 size_t srvstr_get_path(TALLOC_CTX *ctx,
                        const char *inbuf,
                        uint16_t smb_flags2,
@@ -1034,6 +1032,11 @@ void reply_writebmpx(struct smb_request *req);
 void reply_writebs(struct smb_request *req);
 void reply_getattrE(struct smb_request *req);
 
+/* The following definitions come from smbd/smb2_reply.c  */
+
+NTSTATUS check_path_syntax(char *path);
+NTSTATUS check_path_syntax_posix(char *path);
+
 /* The following definitions come from smbd/seal.c  */
 
 bool is_encrypted_packet(const uint8_t *inbuf);
index ff3a6504ddf650d6ecffb5a63468e3ab5ce081ec..8b216681e2fcf702bbc9fc8fe75bd6254eb63d51 100644 (file)
 #include "source3/printing/rap_jobid.h"
 #include "source3/lib/substitute.h"
 
-/****************************************************************************
- Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
- path or anything including wildcards.
- We're assuming here that '/' is not the second byte in any multibyte char
- set (a safe assumption). '\\' *may* be the second byte in a multibyte char
- set.
-****************************************************************************/
-
-/* Custom version for processing POSIX paths. */
-#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
-
-static NTSTATUS check_path_syntax_internal(char *path,
-                                          bool posix_path)
-{
-       char *d = path;
-       const char *s = path;
-       NTSTATUS ret = NT_STATUS_OK;
-       bool start_of_name_component = True;
-       bool stream_started = false;
-       bool last_component_contains_wcard = false;
-
-       while (*s) {
-               if (stream_started) {
-                       switch (*s) {
-                       case '/':
-                       case '\\':
-                               return NT_STATUS_OBJECT_NAME_INVALID;
-                       case ':':
-                               if (s[1] == '\0') {
-                                       return NT_STATUS_OBJECT_NAME_INVALID;
-                               }
-                               if (strchr_m(&s[1], ':')) {
-                                       return NT_STATUS_OBJECT_NAME_INVALID;
-                               }
-                               break;
-                       }
-               }
-
-               if ((*s == ':') && !posix_path && !stream_started) {
-                       if (last_component_contains_wcard) {
-                               return NT_STATUS_OBJECT_NAME_INVALID;
-                       }
-                       /* Stream names allow more characters than file names.
-                          We're overloading posix_path here to allow a wider
-                          range of characters. If stream_started is true this
-                          is still a Windows path even if posix_path is true.
-                          JRA.
-                       */
-                       stream_started = true;
-                       start_of_name_component = false;
-                       posix_path = true;
-
-                       if (s[1] == '\0') {
-                               return NT_STATUS_OBJECT_NAME_INVALID;
-                       }
-               }
-
-               if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
-                       /*
-                        * Safe to assume is not the second part of a mb char
-                        * as this is handled below.
-                        */
-                       /* Eat multiple '/' or '\\' */
-                       while (IS_PATH_SEP(*s,posix_path)) {
-                               s++;
-                       }
-                       if ((d != path) && (*s != '\0')) {
-                               /* We only care about non-leading or trailing '/' or '\\' */
-                               *d++ = '/';
-                       }
-
-                       start_of_name_component = True;
-                       /* New component. */
-                       last_component_contains_wcard = false;
-                       continue;
-               }
-
-               if (start_of_name_component) {
-                       if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
-                               /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
-
-                               /*
-                                * No mb char starts with '.' so we're safe checking the directory separator here.
-                                */
-
-                               /* If  we just added a '/' - delete it */
-                               if ((d > path) && (*(d-1) == '/')) {
-                                       *(d-1) = '\0';
-                                       d--;
-                               }
-
-                               /* Are we at the start ? Can't go back further if so. */
-                               if (d <= path) {
-                                       ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
-                                       break;
-                               }
-                               /* Go back one level... */
-                               /* We know this is safe as '/' cannot be part of a mb sequence. */
-                               /* NOTE - if this assumption is invalid we are not in good shape... */
-                               /* Decrement d first as d points to the *next* char to write into. */
-                               for (d--; d > path; d--) {
-                                       if (*d == '/')
-                                               break;
-                               }
-                               s += 2; /* Else go past the .. */
-                               /* We're still at the start of a name component, just the previous one. */
-                               continue;
-
-                       } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
-                               if (posix_path) {
-                                       /* Eat the '.' */
-                                       s++;
-                                       continue;
-                               }
-                       }
-
-               }
-
-               if (!(*s & 0x80)) {
-                       if (!posix_path) {
-                               if (*s <= 0x1f || *s == '|') {
-                                       return NT_STATUS_OBJECT_NAME_INVALID;
-                               }
-                               switch (*s) {
-                                       case '*':
-                                       case '?':
-                                       case '<':
-                                       case '>':
-                                       case '"':
-                                               last_component_contains_wcard = true;
-                                               break;
-                                       default:
-                                               break;
-                               }
-                       }
-                       *d++ = *s++;
-               } else {
-                       size_t siz;
-                       /* Get the size of the next MB character. */
-                       next_codepoint(s,&siz);
-                       switch(siz) {
-                               case 5:
-                                       *d++ = *s++;
-                                       FALL_THROUGH;
-                               case 4:
-                                       *d++ = *s++;
-                                       FALL_THROUGH;
-                               case 3:
-                                       *d++ = *s++;
-                                       FALL_THROUGH;
-                               case 2:
-                                       *d++ = *s++;
-                                       FALL_THROUGH;
-                               case 1:
-                                       *d++ = *s++;
-                                       break;
-                               default:
-                                       DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
-                                       *d = '\0';
-                                       return NT_STATUS_INVALID_PARAMETER;
-                       }
-               }
-               start_of_name_component = False;
-       }
-
-       *d = '\0';
-
-       return ret;
-}
-
-/****************************************************************************
- Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
- No wildcards allowed.
-****************************************************************************/
-
-NTSTATUS check_path_syntax(char *path)
-{
-       return check_path_syntax_internal(path, false);
-}
-
-/****************************************************************************
- Check the path for a POSIX client.
- We're assuming here that '/' is not the second byte in any multibyte char
- set (a safe assumption).
-****************************************************************************/
-
-NTSTATUS check_path_syntax_posix(char *path)
-{
-       return check_path_syntax_internal(path, true);
-}
-
 /****************************************************************************
  Pull a string and check the path allowing a wildcard - provide for error return.
  Passes in posix flag.
diff --git a/source3/smbd/smb2_reply.c b/source3/smbd/smb2_reply.c
new file mode 100644 (file)
index 0000000..ba5ad64
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+   Unix SMB/CIFS implementation.
+   Main SMB reply routines
+   Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Andrew Bartlett      2001
+   Copyright (C) Jeremy Allison 1992-2007.
+   Copyright (C) Volker Lendecke 2007
+
+   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/>.
+*/
+/*
+   This file handles most of the reply_ calls that the server
+   makes to handle specific protocols
+*/
+
+#include "includes.h"
+#include "libsmb/namequery.h"
+#include "system/filesys.h"
+#include "printing.h"
+#include "locking/share_mode_lock.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "smbd/smbXsrv_open.h"
+#include "fake_file.h"
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_spoolss_c.h"
+#include "rpc_client/cli_spoolss.h"
+#include "rpc_client/init_spoolss.h"
+#include "rpc_server/rpc_ncacn_np.h"
+#include "libcli/security/security.h"
+#include "libsmb/nmblib.h"
+#include "auth.h"
+#include "smbprofile.h"
+#include "../lib/tsocket/tsocket.h"
+#include "lib/util/tevent_ntstatus.h"
+#include "libcli/smb/smb_signing.h"
+#include "lib/util/sys_rw_data.h"
+#include "librpc/gen_ndr/open_files.h"
+#include "smb1_utils.h"
+#include "libcli/smb/smb2_posix.h"
+#include "lib/util/string_wrappers.h"
+#include "source3/printing/rap_jobid.h"
+#include "source3/lib/substitute.h"
+
+/****************************************************************************
+ Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
+ path or anything including wildcards.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption). '\\' *may* be the second byte in a multibyte char
+ set.
+****************************************************************************/
+
+/* Custom version for processing POSIX paths. */
+#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
+
+static NTSTATUS check_path_syntax_internal(char *path,
+                                          bool posix_path)
+{
+       char *d = path;
+       const char *s = path;
+       NTSTATUS ret = NT_STATUS_OK;
+       bool start_of_name_component = True;
+       bool stream_started = false;
+       bool last_component_contains_wcard = false;
+
+       while (*s) {
+               if (stream_started) {
+                       switch (*s) {
+                       case '/':
+                       case '\\':
+                               return NT_STATUS_OBJECT_NAME_INVALID;
+                       case ':':
+                               if (s[1] == '\0') {
+                                       return NT_STATUS_OBJECT_NAME_INVALID;
+                               }
+                               if (strchr_m(&s[1], ':')) {
+                                       return NT_STATUS_OBJECT_NAME_INVALID;
+                               }
+                               break;
+                       }
+               }
+
+               if ((*s == ':') && !posix_path && !stream_started) {
+                       if (last_component_contains_wcard) {
+                               return NT_STATUS_OBJECT_NAME_INVALID;
+                       }
+                       /* Stream names allow more characters than file names.
+                          We're overloading posix_path here to allow a wider
+                          range of characters. If stream_started is true this
+                          is still a Windows path even if posix_path is true.
+                          JRA.
+                       */
+                       stream_started = true;
+                       start_of_name_component = false;
+                       posix_path = true;
+
+                       if (s[1] == '\0') {
+                               return NT_STATUS_OBJECT_NAME_INVALID;
+                       }
+               }
+
+               if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
+                       /*
+                        * Safe to assume is not the second part of a mb char
+                        * as this is handled below.
+                        */
+                       /* Eat multiple '/' or '\\' */
+                       while (IS_PATH_SEP(*s,posix_path)) {
+                               s++;
+                       }
+                       if ((d != path) && (*s != '\0')) {
+                               /* We only care about non-leading or trailing '/' or '\\' */
+                               *d++ = '/';
+                       }
+
+                       start_of_name_component = True;
+                       /* New component. */
+                       last_component_contains_wcard = false;
+                       continue;
+               }
+
+               if (start_of_name_component) {
+                       if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
+                               /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
+
+                               /*
+                                * No mb char starts with '.' so we're safe checking the directory separator here.
+                                */
+
+                               /* If  we just added a '/' - delete it */
+                               if ((d > path) && (*(d-1) == '/')) {
+                                       *(d-1) = '\0';
+                                       d--;
+                               }
+
+                               /* Are we at the start ? Can't go back further if so. */
+                               if (d <= path) {
+                                       ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+                                       break;
+                               }
+                               /* Go back one level... */
+                               /* We know this is safe as '/' cannot be part of a mb sequence. */
+                               /* NOTE - if this assumption is invalid we are not in good shape... */
+                               /* Decrement d first as d points to the *next* char to write into. */
+                               for (d--; d > path; d--) {
+                                       if (*d == '/')
+                                               break;
+                               }
+                               s += 2; /* Else go past the .. */
+                               /* We're still at the start of a name component, just the previous one. */
+                               continue;
+
+                       } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
+                               if (posix_path) {
+                                       /* Eat the '.' */
+                                       s++;
+                                       continue;
+                               }
+                       }
+
+               }
+
+               if (!(*s & 0x80)) {
+                       if (!posix_path) {
+                               if (*s <= 0x1f || *s == '|') {
+                                       return NT_STATUS_OBJECT_NAME_INVALID;
+                               }
+                               switch (*s) {
+                                       case '*':
+                                       case '?':
+                                       case '<':
+                                       case '>':
+                                       case '"':
+                                               last_component_contains_wcard = true;
+                                               break;
+                                       default:
+                                               break;
+                               }
+                       }
+                       *d++ = *s++;
+               } else {
+                       size_t siz;
+                       /* Get the size of the next MB character. */
+                       next_codepoint(s,&siz);
+                       switch(siz) {
+                               case 5:
+                                       *d++ = *s++;
+                                       FALL_THROUGH;
+                               case 4:
+                                       *d++ = *s++;
+                                       FALL_THROUGH;
+                               case 3:
+                                       *d++ = *s++;
+                                       FALL_THROUGH;
+                               case 2:
+                                       *d++ = *s++;
+                                       FALL_THROUGH;
+                               case 1:
+                                       *d++ = *s++;
+                                       break;
+                               default:
+                                       DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
+                                       *d = '\0';
+                                       return NT_STATUS_INVALID_PARAMETER;
+                       }
+               }
+               start_of_name_component = False;
+       }
+
+       *d = '\0';
+
+       return ret;
+}
+
+/****************************************************************************
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
+ No wildcards allowed.
+****************************************************************************/
+
+NTSTATUS check_path_syntax(char *path)
+{
+       return check_path_syntax_internal(path, false);
+}
+
+/****************************************************************************
+ Check the path for a POSIX client.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption).
+****************************************************************************/
+
+NTSTATUS check_path_syntax_posix(char *path)
+{
+       return check_path_syntax_internal(path, true);
+}
index aceb0453f71c37fd6f4d2fc9314d140197974227..8b64cbe8e3ccd41006297753c9dd2998cd665423 100644 (file)
@@ -631,6 +631,7 @@ bld.SAMBA3_LIBRARY('smbd_base',
                           smbd/smb2_nttrans.c
                           smbd/smb2_pipes.c
                           smbd/reply.c
+                          smbd/smb2_reply.c
                           smbd/trans2.c
                           smbd/uid.c
                           smbd/dosmode.c