svn commit: samba r12194 - in branches/SAMBA_3_0/source/smbd: .

jra at samba.org jra at samba.org
Mon Dec 12 18:22:01 GMT 2005


Author: jra
Date: 2005-12-12 18:21:59 +0000 (Mon, 12 Dec 2005)
New Revision: 12194

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=12194

Log:
Ensure that when we set a connection path we've canonicalized
the name (must be abolute - start with /, must not end in /,
must have ./ and ../ removed). Of course for realpath resolved
paths this won't be the case but for others we need this name
to be canonicalized. This name is going into the sharemode db
for #3303 so needs to be in a normalized format.
Jeremy.

Modified:
   branches/SAMBA_3_0/source/smbd/msdfs.c
   branches/SAMBA_3_0/source/smbd/posix_acls.c
   branches/SAMBA_3_0/source/smbd/reply.c
   branches/SAMBA_3_0/source/smbd/service.c


Changeset:
Modified: branches/SAMBA_3_0/source/smbd/msdfs.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/msdfs.c	2005-12-12 14:08:42 UTC (rev 12193)
+++ branches/SAMBA_3_0/source/smbd/msdfs.c	2005-12-12 18:21:59 UTC (rev 12194)
@@ -146,7 +146,7 @@
                 return False;
         }
 	
-	string_set(&conn->connectpath, connpath);
+	set_conn_connectpath(conn, connpath);
 
 	if (!smbd_vfs_init(conn)) {
 		DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n"));

Modified: branches/SAMBA_3_0/source/smbd/posix_acls.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/posix_acls.c	2005-12-12 14:08:42 UTC (rev 12193)
+++ branches/SAMBA_3_0/source/smbd/posix_acls.c	2005-12-12 18:21:59 UTC (rev 12194)
@@ -4220,7 +4220,7 @@
 	connection_struct conn;
 	files_struct finfo;
 	struct fd_handle fh;
-	fstring path;
+	pstring path;
 	pstring filename;
 	
 	ZERO_STRUCT( conn );
@@ -4231,8 +4231,8 @@
 		return NULL;
 	}
 	
-	fstrcpy( path, "/" );
-	string_set(&conn.connectpath, path);
+	pstrcpy( path, "/" );
+	set_conn_connectpath(&conn, path);
 	
 	if (!smbd_vfs_init(&conn)) {
 		DEBUG(0,("novfs_get_nt_acl: Unable to create a fake connection struct!\n"));

Modified: branches/SAMBA_3_0/source/smbd/reply.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/reply.c	2005-12-12 14:08:42 UTC (rev 12193)
+++ branches/SAMBA_3_0/source/smbd/reply.c	2005-12-12 18:21:59 UTC (rev 12194)
@@ -4954,7 +4954,7 @@
 	} else {
 		ok = vfs_directory_exist(conn,newdir,NULL);
 		if (ok)
-			string_set(&conn->connectpath,newdir);
+			set_conn_connectpath(conn,newdir);
 	}
   
 	if (!ok) {

Modified: branches/SAMBA_3_0/source/smbd/service.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/service.c	2005-12-12 14:08:42 UTC (rev 12193)
+++ branches/SAMBA_3_0/source/smbd/service.c	2005-12-12 18:21:59 UTC (rev 12194)
@@ -24,6 +24,105 @@
 extern userdom_struct current_user_info;
 
 /****************************************************************************
+ Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
+ absolute path stating in / and not ending in /.
+ Observent people will notice a similarity between this and check_path_syntax :-).
+****************************************************************************/
+
+void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
+{
+	pstring destname;
+	char *d = destname;
+	const char *s = connectpath;
+        BOOL start_of_name_component = True;
+
+	*d++ = '/'; /* Always start with root. */
+
+	while (*s) {
+		if (*s == '/') {
+			/* Eat multiple '/' */
+			while (*s == '/') {
+                                s++;
+                        }
+			if ((d != destname) && (*s != '\0')) {
+				*d++ = '/';
+			}
+			start_of_name_component = True;
+			continue;
+		}
+
+		if (start_of_name_component) {
+			if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
+				/* Uh oh - "/../" or "/..\0" ! */
+
+				/* Go past the ../ or .. */
+				if (s[2] == '/') {
+					s += 3;
+				} else {
+					s += 2; /* Go past the .. */
+				}
+
+				/* 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) {
+					*d++ = '/'; /* Can't delete root */
+					continue;
+				}
+				/* Go back one level... */
+				/* Decrement d first as d points to the *next* char to write into. */
+				for (d--; d > destname; d--) {
+					if (*d == '/') {
+						break;
+					}
+				}
+				/* We're still at the start of a name component, just the previous one. */
+				continue;
+			} else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
+				/* Component of pathname can't be "." only - skip the '.' . */
+				if (s[1] == '/') {
+					s += 2;
+				} else {
+					s++;
+				}
+				continue;
+			}
+		}
+
+		if (!(*s & 0x80)) {
+			*d++ = *s++;
+		} 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:
+					break;
+			}
+		}
+		start_of_name_component = False;
+	}
+	*d = '\0';
+
+	/* And must not end in '/' */
+	if (d > destname + 1 && (*(d-1) == '/')) {
+		*(d-1) = '\0';
+	}
+
+	string_set(&conn->connectpath, destname);
+}
+
+/****************************************************************************
  Load parameters specific to a connection/service.
 ****************************************************************************/
 
@@ -474,7 +573,7 @@
 		pstring s;
 		pstrcpy(s,lp_pathname(snum));
 		standard_sub_conn(conn,s,sizeof(s));
-		string_set(&conn->connectpath,s);
+		set_conn_connectpath(conn,s);
 		DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
 	}
 
@@ -537,7 +636,7 @@
 		pstring s;
 		pstrcpy(s,conn->connectpath);
 		canonicalize_path(conn, s);
-		string_set(&conn->connectpath,s);
+		set_conn_connectpath(conn,s);
 	}
 
 /* ROOT Activities: */	
@@ -652,7 +751,7 @@
 		pstring s;
 		pstrcpy(s,conn->connectpath);
 		vfs_GetWd(conn,s);
-		string_set(&conn->connectpath,s);
+		set_conn_connectpath(conn,s);
 		vfs_ChDir(conn,conn->connectpath);
 	}
 #endif



More information about the samba-cvs mailing list