s3: smbd: Make set_conn_connectpath() call canonicalize_absolute_path().
authorJeremy Allison <jra@samba.org>
Tue, 17 Jan 2017 19:35:52 +0000 (11:35 -0800)
committerJeremy Allison <jra@samba.org>
Mon, 30 Jan 2017 17:39:18 +0000 (18:39 +0100)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Uri Simchoni <uri@samba.org>
source3/smbd/service.c

index ce4b8da1e245e26c6ba16c72f4221f575170a04f..0376a330e23ca2a7053e6155b7a02f7e79c58abc 100644 (file)
@@ -31,6 +31,7 @@
 #include "lib/param/loadparm.h"
 #include "messages.h"
 #include "lib/afs/afs_funcs.h"
+#include "lib/util_path.h"
 
 static bool canonicalize_connect_path(connection_struct *conn)
 {
@@ -47,118 +48,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 ));