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
