]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
r6048: Split out the check_path_syntax into a findfirst/next/wildcard version.
authorJeremy Allison <jra@samba.org>
Thu, 24 Mar 2005 22:32:52 +0000 (22:32 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:56:18 +0000 (10:56 -0500)
The semantics are different with wildcards.
Jeremy.

source/smbd/msdfs.c
source/smbd/reply.c

index 184dde1635437956a02727fa9e2549b4c277fcc8..36baff80224830f4335d60f36a28de0bf6cdc404 100644 (file)
@@ -64,7 +64,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp)
        DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename));
 
        /* rest is reqpath */
-       check_path_syntax(pdp->reqpath, p+1,True);
+       check_path_syntax(pdp->reqpath, p+1);
 
        DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath));
        return True;
@@ -110,7 +110,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp)
        DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename));
 
        /* rest is reqpath */
-       check_path_syntax(pdp->reqpath, p+1,True);
+       check_path_syntax(pdp->reqpath, p+1);
 
        DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath));
        return True;
index e8ee9ffe92067dd9d7783aa821a1945213453d4f..059af830017f70832fa43901d92e4994cf1a7c28 100644 (file)
@@ -38,13 +38,13 @@ extern uint32 global_client_caps;
 extern BOOL global_encrypted_passwords_negotiated;
 
 /****************************************************************************
- Ensure we check the path in *exactly* the same way as W2K.
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
  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.
 ****************************************************************************/
 
-NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
 {
        char *d = destname;
        const char *s = srcname;
@@ -118,20 +118,16 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w
                }
 
                if (!(*s & 0x80)) {
-                       if (allow_wcard_names) {
-                               *d++ = *s++;
-                       } else {
-                               switch (*s) {
-                                       case '*':
-                                       case '?':
-                                       case '<':
-                                       case '>':
-                                       case '"':
-                                               return NT_STATUS_OBJECT_NAME_INVALID;
-                                       default:
-                                               *d++ = *s++;
-                                               break;
-                               }
+                       switch (*s) {
+                               case '*':
+                               case '?':
+                               case '<':
+                               case '>':
+                               case '"':
+                                       return NT_STATUS_OBJECT_NAME_INVALID;
+                               default:
+                                       *d++ = *s++;
+                                       break;
                        }
                } else {
                        switch(next_mb_char_size(s)) {
@@ -157,17 +153,127 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w
        }
 
        if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
-               /* For some strange reason being called from findfirst changes
-                  the num_components number to cause the error return to change. JRA. */
-               if (allow_wcard_names) {
-                       if (num_bad_components > 2) {
-                               ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               if (num_bad_components > 1) {
+                       ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               }
+       }
+
+       *d = '\0';
+       return ret;
+}
+
+/****************************************************************************
+ 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.
+****************************************************************************/
+
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
+{
+       char *d = destname;
+       const char *s = srcname;
+       NTSTATUS ret = NT_STATUS_OK;
+       BOOL start_of_name_component = True;
+       unsigned int num_bad_components = 0;
+
+       while (*s) {
+               if (IS_DIRECTORY_SEP(*s)) {
+                       /*
+                        * Safe to assume is not the second part of a mb char as this is handled below.
+                        */
+                       /* Eat multiple '/' or '\\' */
+                       while (IS_DIRECTORY_SEP(*s)) {
+                               s++;
+                       }
+                       if ((d != destname) && (*s != '\0')) {
+                               /* We only care about non-leading or trailing '/' or '\\' */
+                               *d++ = '/';
+                       }
+
+                       start_of_name_component = True;
+                       continue;
+               }
+
+               if (start_of_name_component) {
+                       if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || 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 > destname) && (*(d-1) == '/')) {
+                                       *(d-1) = '\0';
+                                       d--;
+                               }
+
+                               /* Are we at the start ? Can't go back further if so. */
+                               if (d <= destname) {
+                                       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 > destname; d--) {
+                                       if (*d == '/')
+                                               break;
+                               }
+                               s += 2; /* Else go past the .. */
+                               /* We're still at the start of a name component, just the previous one. */
+
+                               if (num_bad_components) {
+                                       /* Hmmm. Should we only decrement the bad_components if
+                                          we're removing a bad component ? Need to check this. JRA. */
+                                       num_bad_components--;
+                               }
+
+                               continue;
+
+                       } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
+                               /* Component of pathname can't be "." only. */
+                               ret =  NT_STATUS_OBJECT_NAME_INVALID;
+                               num_bad_components++;
+                               *d++ = *s++;
+                               continue;
                        }
+               }
+
+               if (!(*s & 0x80)) {
+                       *d++ = *s++;
                } else {
-                       if (num_bad_components > 1) {
-                               ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+                       switch(next_mb_char_size(s)) {
+                               case 4:
+                                       *d++ = *s++;
+                               case 3:
+                                       *d++ = *s++;
+                               case 2:
+                                       *d++ = *s++;
+                               case 1:
+                                       *d++ = *s++;
+                                       break;
+                               default:
+                                       DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
+                                       *d = '\0';
+                                       return NT_STATUS_INVALID_PARAMETER;
                        }
                }
+               if (start_of_name_component && num_bad_components) {
+                       num_bad_components++;
+               }
+               start_of_name_component = False;
+       }
+
+       if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
+               /* For some strange reason being called from findfirst changes
+                  the num_components number to cause the error return to change. JRA. */
+               if (num_bad_components > 2) {
+                       ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               }
        }
 
        *d = '\0';
@@ -192,7 +298,11 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
        } else {
                ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
        }
-       *err = check_path_syntax(dest, tmppath, allow_wcard_names);
+       if (allow_wcard_names) {
+               *err = check_path_syntax_wcard(dest, tmppath);
+       } else {
+               *err = check_path_syntax(dest, tmppath);
+       }
        return ret;
 }