From 6b5d954ec76cb3c1c8bf69e8572ad147ca60cb1d Mon Sep 17 00:00:00 2001 From: Slawomir Bochenski Date: Mon, 1 Aug 2011 15:44:57 +0200 Subject: [PATCH] obexd: Fix valid file name checks for FTP & OPP Until now adversary could exploit OBEX Name header and perform any kind of operations (listing, getting, putting) outside of given root by putting path with ".." components inside this header. --- obexd/plugins/filesystem.c | 13 +++++++++++++ obexd/plugins/filesystem.h | 1 + obexd/plugins/ftp.c | 9 ++++++++- obexd/plugins/opp.c | 6 ++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/obexd/plugins/filesystem.c b/obexd/plugins/filesystem.c index 041cca65d..8d1d74b00 100644 --- a/obexd/plugins/filesystem.c +++ b/obexd/plugins/filesystem.c @@ -87,6 +87,19 @@ static const uint8_t FTP_TARGET[TARGET_SIZE] = { static const uint8_t PCSUITE_WHO[PCSUITE_WHO_SIZE] = { 'P', 'C', ' ', 'S', 'u', 'i', 't', 'e' }; +gboolean is_filename(const char *name) +{ + if (strchr(name, '/')) + return FALSE; + + if (strcmp(name, ".") == 0) + return FALSE; + + if (strcmp(name, "..") == 0) + return FALSE; + + return TRUE; +} static char *file_stat_line(char *filename, struct stat *fstat, struct stat *dstat, gboolean root, diff --git a/obexd/plugins/filesystem.h b/obexd/plugins/filesystem.h index 9c7ad9aa3..3c6d2c19e 100644 --- a/obexd/plugins/filesystem.h +++ b/obexd/plugins/filesystem.h @@ -22,3 +22,4 @@ */ ssize_t string_read(void *object, void *buf, size_t count); +gboolean is_filename(const char *name); diff --git a/obexd/plugins/ftp.c b/obexd/plugins/ftp.c index 8e17b6f79..57b187cca 100644 --- a/obexd/plugins/ftp.c +++ b/obexd/plugins/ftp.c @@ -51,6 +51,7 @@ #include "mimetype.h" #include "service.h" #include "ftp.h" +#include "filesystem.h" #define LST_TYPE "x-obex/folder-listing" #define CAP_TYPE "x-obex/capability" @@ -182,6 +183,9 @@ static int get_by_type(struct ftp_session *ftp, const char *type) if (type != NULL && g_ascii_strcasecmp(type, CAP_TYPE) == 0) return obex_get_stream_start(os, capability); + if (name != NULL && !is_filename(name)) + return -EBADR; + path = g_build_filename(ftp->folder, name, NULL); err = obex_get_stream_start(os, path); @@ -289,6 +293,9 @@ int ftp_put(struct obex_session *os, obex_object_t *obj, void *user_data) if (name == NULL) return -EBADR; + if (!is_filename(name)) + return -EBADR; + if (size == OBJECT_SIZE_DELETE) return ftp_delete(ftp, name); @@ -344,7 +351,7 @@ int ftp_setpath(struct obex_session *os, obex_object_t *obj, void *user_data) } /* Check and set to name path */ - if (strstr(name, "/") || strcmp(name, "..") == 0) { + if (!is_filename(name)) { error("Set path failed: name incorrect!"); return -EPERM; } diff --git a/obexd/plugins/opp.c b/obexd/plugins/opp.c index 59371101e..644a2c675 100644 --- a/obexd/plugins/opp.c +++ b/obexd/plugins/opp.c @@ -39,6 +39,7 @@ #include "service.h" #include "log.h" #include "dbus.h" +#include "filesystem.h" #define VCARD_TYPE "text/x-vcard" #define VCARD_FILE CONFIGDIR "/vcard.vcf" @@ -114,10 +115,15 @@ static int opp_chkput(struct obex_session *os, void *user_data) char *path; int32_t time; int ret; + const char *t; if (obex_get_size(os) == OBJECT_SIZE_DELETE) return -EINVAL; + t = obex_get_name(os); + if (t != NULL && !is_filename(t)) + return -EBADR; + if (obex_get_auto_accept(os)) { folder = g_strdup(obex_get_root_folder(os)); name = g_strdup(obex_get_name(os)); -- 2.47.3