Subject: [PATCH 04/35] s3: smbd: Make set_conn_connectpath() call canonicalize_absolute_path().

From: Jeremy Allison <[email-masked]>
Date: Tue, 17 Jan 2017 11:35:52 -0800

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531

Signed-off-by: Jeremy Allison <[email-masked]>
Reviewed-by: Uri Simchoni <[email-masked]>
(backported from commit d650d65488761b30fa34d42cb1ab400618a78c33)
---
 source3/smbd/service.c | 102 +------------------------------------------------
 1 file changed, 2 insertions(+), 100 deletions(-)

diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index d11987e63ee..19be912ec7e 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -47,118 +47,20 @@ static bool canonicalize_connect_path(connection_struct *conn)
 /****************************************************************************
  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 :-).
 ****************************************************************************/
 
 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
 {
 	char *destname;
-	char *d;
-	const char *s = connectpath;
-        bool start_of_name_component = true;
 
 	if (connectpath == NULL || connectpath[0] == '\0') {
 		return false;
 	}
 
-	/* Allocate for strlen + '\0' + possible leading '/' */
-	destname = (char *)talloc_size(conn, strlen(connectpath) + 2);
-	if (!destname) {
+	destname = canonicalize_absolute_path(conn, connectpath);
+	if (destname == NULL) {
 		return false;
 	}
-	d = destname;
-
-	*d++ = '/'; /* Always start with root. */
-
-	while (*s) {
-		if (*s == '/') {
-			/* Eat multiple '/' */
-			while (*s == '/') {
-                                s++;
-                        }
-			if ((d > destname + 1) && (*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 {
-			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:
-					break;
-			}
-		}
-		start_of_name_component = false;
-	}
-	*d = '\0';
-
-	/* And must not end in '/' */
-	if (d > destname + 1 && (*(d-1) == '/')) {
-		*(d-1) = '\0';
-	}
 
 	DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
 		lp_servicename(talloc_tos(), SNUM(conn)), destname ));
-- 
2.12.0.rc1.440.g5b76565f74-goog