Author: jra
Date: 2004-09-02 22:35:45 +0000 (Thu, 02 Sep 2004)
New Revision: 2195

WebSVN: 
http://websvn.samba.org/websvn/changeset.php?rep=samba&path=/trunk/source/smbd&rev=2195&nolog=1

Log:
Here is the efforts of much pain reproducing W2K3 pathname
parsing. :-(. One more check for CreateFile() needed.
Jeremy.

Modified:
   trunk/source/smbd/reply.c
   trunk/source/smbd/trans2.c


Changeset:
Modified: trunk/source/smbd/reply.c
===================================================================
--- trunk/source/smbd/reply.c   2004-09-02 22:35:36 UTC (rev 2194)
+++ trunk/source/smbd/reply.c   2004-09-02 22:35:45 UTC (rev 2195)
@@ -48,6 +48,7 @@
        char *d = destname;
        const char *s = srcname;
        NTSTATUS ret = NT_STATUS_OK;
+       BOOL start_of_name_component = True;
 
        while (*s) {
                if (IS_DIRECTORY_SEP(*s)) {
@@ -58,100 +59,109 @@
                        while (IS_DIRECTORY_SEP(*s)) {
                                s++;
                        }
-                       if ((s[0] == '.') && (s[1] == '\0')) {
-                               ret = NT_STATUS_OBJECT_NAME_INVALID;
-                               break;
-                       }
                        if ((d != destname) && (*s != '\0')) {
                                /* We only care about non-leading or trailing '/' or 
'\\' */
                                *d++ = '/';
                        }
-               } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) 
|| s[2] == '\0')) {
-                       /* Uh oh - "../" or "..\\"  or "..\0" ! */
 
-                       /*
-                        * No mb char starts with '.' so we're safe checking the 
directory separator here.
-                        */
+                       start_of_name_component = True;
+                       continue;
+               }
 
-                       /* If we just added a '/', delete it. */
+               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" 
! */
 
-                       if ((d > destname) && (*(d-1) == '/')) {
-                               *(d-1) = '\0';
-                               if (d == (destname + 1)) {
+                               /*
+                                * 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--;
-                               } else {
-                                       d -= 2;
                                }
-                       }
-                       /* 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... */
-                       while (d > destname) {
-                               if (*d == '/')
+
+                               /* Are we at the start ? Can't go back further if so. 
*/
+                               if (d <= destname) {
+                                       ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                                        break;
-                               d--;
-                       }
-                       s += 3;
-               } else if ((s[0] == '.') && (s[1] == '\0')) {
-                       if (s == srcname) {
-                               ret = NT_STATUS_OBJECT_NAME_INVALID;
+                               }
+                               /* 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. */
+                               continue;
+
+                       } else if ((s[0] == '.') && (s[1] == '\0')) {
+                               /* Component of pathname can't be "." only. */
+                               ret =  NT_STATUS_OBJECT_NAME_INVALID;
                                break;
-                       }
-                       *d++ = *s++;
-               } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
-                       /*
-                        * No mb char starts with '.' so we're safe checking the 
directory separator here.
-                        */
+                       } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
+                               /*
+                                * No mb char starts with '.' so we're safe checking 
the directory separator here.
+                                */
 
-                       /* "./" or ".\\" fails with a different error depending on 
what is after it... */
+                               /* Component of pathname can't be ".\\ANYTHING". */
 
-                       if (s[2] == '\0') {
-                               ret = NT_STATUS_OBJECT_NAME_INVALID;
-                       } else {
-                               ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                       }
-                       break;
-               } else {
-                       if (!(*s & 0x80)) {
-                               if (allow_wcard_names) {
-                                       *d++ = *s++;
+                               /* "/./" or "\\.\\" fails with a different error 
depending on what is after it... */
+
+                               /* Eat multiple '/' or '\\' */
+                               for (s++; IS_DIRECTORY_SEP(*s); s++) {
+                                       ;       
+                               }
+
+                               if (*s == '\0') {
+                                       ret = NT_STATUS_OBJECT_NAME_INVALID;
                                } else {
-                                       switch (*s) {
-                                               case '*':
-                                               case '?':
-                                               case '<':
-                                               case '>':
-                                               case '"':
-                                                       return 
NT_STATUS_OBJECT_NAME_INVALID;
-                                               default:
-                                                       *d++ = *s++;
-                                                       break;
-                                       }
+                                       ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
                                }
+                               break;
+                       }
+               }
+
+               if (!(*s & 0x80)) {
+                       if (allow_wcard_names) {
+                               *d++ = *s++;
                        } else {
-                               switch(next_mb_char_size(s)) {
-                                       case 4:
+                               switch (*s) {
+                                       case '*':
+                                       case '?':
+                                       case '<':
+                                       case '>':
+                                       case '"':
+                                               return NT_STATUS_OBJECT_NAME_INVALID;
+                                       default:
                                                *d++ = *s++;
-                                       case 3:
-                                               *d++ = *s++;
-                                       case 2:
-                                               *d++ = *s++;
-                                       case 1:
-                                               *d++ = *s++;
                                                break;
-                                       default:
-                                               DEBUG(0,("check_path_syntax: character 
length assumptions invalid !\n"));
-                                               *d = '\0';
-                                               return NT_STATUS_INVALID_PARAMETER;
                                }
                        }
+               } else {
+                       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: character length 
assumptions invalid !\n"));
+                                       *d = '\0';
+                                       return NT_STATUS_INVALID_PARAMETER;
+                       }
                }
+               start_of_name_component = False;
        }
+
        *d = '\0';
        return ret;
 }

Modified: trunk/source/smbd/trans2.c
===================================================================
--- trunk/source/smbd/trans2.c  2004-09-02 22:35:36 UTC (rev 2194)
+++ trunk/source/smbd/trans2.c  2004-09-02 22:35:45 UTC (rev 2195)
@@ -1381,6 +1381,11 @@
 
        srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, 
STR_TERMINATE, &ntstatus, True);
        if (!NT_STATUS_IS_OK(ntstatus)) {
+               /* W2k3 never seems to return OBJECT_PATH_NOT_FOUND on a
+                  bad pathname parse in a findfirst, but always OBJECT_NAME_INVALID. 
JRA */
+               /* It remains to be seen what it does on CreateFile(). JRA. (ie. I 
need to check) */
+               if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,ntstatus))
+                       return ERROR_NT(NT_STATUS_OBJECT_NAME_INVALID);
                return ERROR_NT(ntstatus);
        }
 

Reply via email to