summaryrefslogtreecommitdiff
path: root/source3/smbd/service.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2017-01-17 11:35:52 -0800
committerJeremy Allison <jra@samba.org>2017-01-30 18:39:18 +0100
commitd650d65488761b30fa34d42cb1ab400618a78c33 (patch)
treee84e72353ee03e5e7b209d65caf2e3041e8507da /source3/smbd/service.c
parenta51363309a4330b65e34ae941ec99d180bdbab56 (diff)
downloadsamba-d650d65488761b30fa34d42cb1ab400618a78c33.tar.gz
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>
Diffstat (limited to 'source3/smbd/service.c')
-rw-r--r--source3/smbd/service.c103
1 files changed, 3 insertions, 100 deletions
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index ce4b8da1e24..0376a330e23 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -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 ));