summaryrefslogtreecommitdiffstats
path: root/source/smbd
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2004-09-09 15:32:06 +0000
committerGerald Carter <jerry@samba.org>2004-09-09 15:32:06 +0000
commit34f310caafa4dcaa834a7912ed5ae9415ca859a5 (patch)
tree44d2a91554004b29847573d8d99ab3030a4c6d46 /source/smbd
parentdce8dc898b448c994ecb901dd3611394c2544214 (diff)
downloadsamba-34f310caafa4dcaa834a7912ed5ae9415ca859a5.tar.gz
samba-34f310caafa4dcaa834a7912ed5ae9415ca859a5.tar.xz
samba-34f310caafa4dcaa834a7912ed5ae9415ca859a5.zip
r2268: More merges
svn merge -r 2263:2264 $SVNURL/branches/SAMBA_3_0 svn merge -r 2198:2210 $SVNURL/branches/SAMBA_3_0 copy trans2.c and reply.c from 3.0 (jra's pathname parsing)
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/reply.c170
1 files changed, 91 insertions, 79 deletions
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 611fb04c19b..565046061cc 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -48,6 +48,8 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w
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)) {
@@ -58,101 +60,115 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w
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] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) {
+ }
+ /* 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. */
- /*
- * No mb char starts with '.' so we're safe checking the directory separator here.
- */
+ 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--;
+ }
- /* "./" or ".\\" fails with a different error depending on where it is... */
+ continue;
- if (s == srcname) {
- ret = NT_STATUS_OBJECT_NAME_INVALID;
- break;
- } else {
- if (s[1] != '\0' && s[2] == '\0') {
- ret = NT_STATUS_INVALID_PARAMETER;
- break;
- }
- ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- break;
+ } 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;
}
- s++;
- } else {
- 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;
- }
- }
+ }
+
+ if (!(*s & 0x80)) {
+ if (allow_wcard_names) {
+ *d++ = *s++;
} else {
- switch(next_mb_char_size(s)) {
- case 4:
- *d++ = *s++;
- case 3:
- *d++ = *s++;
- case 2:
- *d++ = *s++;
- case 1:
+ switch (*s) {
+ case '*':
+ case '?':
+ case '<':
+ case '>':
+ case '"':
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ default:
*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;
+ }
+ }
+ 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 (allow_wcard_names) {
+ if (num_bad_components > 2) {
+ ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ } else {
+ if (num_bad_components > 1) {
+ ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
}
}
+
*d = '\0';
return ret;
}
@@ -521,7 +537,6 @@ int reply_ioctl(connection_struct *conn,
int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
- int mode;
pstring name;
BOOL ok = False;
BOOL bad_path = False;
@@ -544,8 +559,6 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
- mode = SVAL(inbuf,smb_vwv0);
-
if (check_name(name,conn)) {
if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
if (!(ok = S_ISDIR(sbuf.st_mode))) {
@@ -578,8 +591,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
}
outsize = set_message(outbuf,0,0,True);
-
- DEBUG(3,("chkpth %s mode=%d\n", name, mode));
+ DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
END_PROFILE(SMBchkpth);
return(outsize);