1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-24 02:04:21 +03:00

s3: smbd: Make set_conn_connectpath() call canonicalize_absolute_path().

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>
This commit is contained in:
Jeremy Allison 2017-01-17 11:35:52 -08:00
parent a51363309a
commit d650d65488

View 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 ));