You are not logged in.
SOLVED: Used
man 3 realpath
Hello Archers,
I have this one problem I've been struggling with. I kind of solved it but the solution's hackish.
My question is how do you prevent the opening of files "above" a specified directory? The reason behind this is that I'm writing a simple sharing server, something like Xyne's quickserve, but in C and with a GTK GUI. I'm using the libmicrohttpd library.
The program works this way: the user selects a port and a directory to be "served", and then he can access the files under the directory he chose. However, there obviously needs to be a way to prevent the user from opening files above the directory by using ".."'s for example.
For now, I simply plan on rejecting all queries containing ".." (http://github.com/houbysoft/quickshare/ … hare.c#L59), but that's obviously very imperfect -- and you could get around it if there is a symlink in the directory for example.
Any pointers will be very appreciated, thanks.
Last edited by y27 (2010-03-17 02:59:14)
Offline
chroot()? Though you need root privileges for that to work.
** edit: s/priveleges/privileges/
Last edited by Peasantoid (2010-03-16 20:57:58)
Offline
Thanks, didn't think of that, but I can't use that anyway since the program needs to run under normal users.
Offline
Why not just parse the query they pass to your server before processing to ensure that the request falls within your new "root" structure?
Offline
Well that's kind of what I'm doing, by checking for "..". I also guess I could check symlinks, etc., and always try to resolve the path into its full form and then check, but isn't there a simpler way?
Offline
I don't think there's any easy way other than chroot(). My two ideas are:
- Make your program setuid, use chroot(), then drop root privileges
- Using whatever logic readlink -f uses, resolve the pathname, then check if it begins with the allowed directory
Offline
@tavianator:
Thanks mainly for the second suggestion which made me get the coreutils source code; and I learned what this "path resolving" is called (canonicalizing), so I knew what to google for.
I found a function very suitable to my needs :
man 3 realpath
I now check if it begins with the allowed directory (and if that's where the directory name ends, so that somebody can't access for example with the path /test/blah/something123 when the base directory is set /test/blah/something12).
I marked this as SOLVED, thanks everybody for assistance.
Offline
BUGS
The POSIX.1-2001 standard version of this function is broken by design, since it is impossible to
determine a suitable size for the output buffer, resolved_path. According to POSIX.1-2001 a buffer
of size PATH_MAX suffices, but PATH_MAX need not be a defined constant, and may have to be obtained
using pathconf(3). And asking pathconf(3) does not really help, since, on the one hand POSIX warns
that the result of pathconf(3) may be huge and unsuitable for mallocing memory, and on the other
hand pathconf(3) may return -1 to signify that PATH_MAX is not bounded. The resolved_path == NULL
feature, not standardized in POSIX.1-2001, but standardized in POSIX.1-2008, allows this design
problem to be avoided.
So be careful to either pass resolved_path as NULL and bite the potential unportablilty bullet, or copy canonicalize_file_name or canonicalize_filename_mode from gnulib.
Last edited by tavianator (2010-03-17 03:36:21)
Offline
@tavianator:
Thanks mainly for the second suggestion which made me get the coreutils source code; and I learned what this "path resolving" is called (canonicalizing), so I knew what to google for.I found a function very suitable to my needs :
man 3 realpath
I now check if it begins with the allowed directory (and if that's where the directory name ends, so that somebody can't access for example with the path /test/blah/something123 when the base directory is set /test/blah/something12).
I marked this as SOLVED, thanks everybody for assistance.
Didn't know about that function, but it seems the most elegant way of doing it
Offline
man realpath wrote:BUGS
The POSIX.1-2001 standard version of this function is broken by design, since it is impossible to
determine a suitable size for the output buffer, resolved_path. According to POSIX.1-2001 a buffer
of size PATH_MAX suffices, but PATH_MAX need not be a defined constant, and may have to be obtained
using pathconf(3). And asking pathconf(3) does not really help, since, on the one hand POSIX warns
that the result of pathconf(3) may be huge and unsuitable for mallocing memory, and on the other
hand pathconf(3) may return -1 to signify that PATH_MAX is not bounded. The resolved_path == NULL
feature, not standardized in POSIX.1-2001, but standardized in POSIX.1-2008, allows this design
problem to be avoided.So be careful to either pass resolved_path as NULL and bite the potential unportablilty bullet, or copy canonicalize_file_name or canonicalize_filename_mode from gnulib.
Yeah, I am passing NULL.
Offline