5

I have written a small custom web server application in C running on Linux. When the application receives a request it calls fork() and handles the request in a separate process, which is chrooted into a specific directory containing the files I want to make available.

I want to port the application to Windows, but neither fork() nor chroot() are available on this platform, and there don't seem to be any direct equivalents. Can you point me to a simple (and preferably well written) example of code that will provide this functionality in Windows? My C isn't all that good, so the simpler the better.

codebox
  • 19,927
  • 9
  • 63
  • 81
  • Answers so far indicate that there is no simple alternative to fork(), I am happy to consider using separate threads rather than forking a new process, but would still like a code example. There are plenty of web servers that run on Windows (eg Apache) which must address both the fork() and the chroot() parts of this problem, would accept a brief summary of the approach that is typically taken and links to the relevant parts of the Apache (or other) source. – codebox Nov 10 '09 at 09:39
  • Given your comment, I would suggest that you do not base your code on the Cygwin sample source, but instead use the Apache Portable Runtime library to take care of the details for you. – Michael Dillon Nov 10 '09 at 16:16
  • I too think you should go with some library. Also see: http://www.gnu.org/software/libmicrohttpd/ - An HTTP server library with support for both Windows and Unix. Used to embed web server functionality in your program. http://abyss.sourceforge.net/ - web server for win/unix Also, you could forget about threads and processes and use non-blocking IO. This way you only need one process, instead you keep track of connections in a list or array. An example: http://www.cubicsky.com/files/shinyhttpd-0.1.3-src.tar.gz – Prof. Falken Nov 11 '09 at 06:36
  • I've ended up using threads for this, rather than fork - unfortunately as a result I've had to rework some of my existing code to make it thread-safe which fork does not require. For the chroot part of the problem I think I'm going to have to check the file paths myself, this looks like a good approach to detect attempts to walk up the directory tree by inserting '../..' into the URL http://msdn.microsoft.com/en-us/library/bb773569(VS.85).aspx – codebox Nov 17 '09 at 08:17

6 Answers6

9

First of all, the Windows equivalent of chroot is RUNAS which is documented here. If you need to do this from a program, then studying this C++ source code should help you understand how to use the Windows API. It is not precisely the same as chroot() but Windows folk use it to create something like a chroot jail by creating a user with extremely limited permissions and only giving that user read permission on the application folder, and write permission on one folder for data.

You probably don't want to exactly emulate fork() on Windows because it doesn't sound like you need to go that far. To understand the Windows API for creating processes and how it differs from fork(), check Mr. Peabody Explains fork(). The actual current source code for Cygwin's fork implementation shows you the current state of the art.

The Microsoft documentation for CreateProcess() and CreateThread() are the place to look for more info on the differences between them.

And finally, if you don't want to learn all the nitty-gritty platform details, just write portable programs that work on Windows and Unix, why not just use the Apache Portable Runtime library itself. Here are some docs on process creation with some sample code, in C, to create a new process.

Michael Dillon
  • 31,973
  • 6
  • 70
  • 106
  • 1
    That's not `chroot()`, `chroot` changes your root directory, not which user you are identified as – Hasturkun Nov 10 '09 at 16:24
  • 4
    You are right, it is not chroot() because Windows does not have chroot(), but RUNAS.EXE is what Windows folks use to create something similar to the UNIX chroot jail. – Michael Dillon Nov 10 '09 at 18:45
  • 3
    RUNAS is not similar to a chroot jail. –  Nov 16 '09 at 22:35
  • As to Apache Portable Runtime library; There's [apr_proc_fork](http://apr.apache.org/docs/apr/0.9/group__apr__thread__proc.html#g3d0415bf69b0a629a929833e82758b85) function with the following note: *This is currently the only non-portable call in APR. This executes a standard unix fork.* I take it to mean there's no fork() in APR outsie of *nix. If I'm wrong please clarify. – Piotr Dobrogost Mar 20 '11 at 18:56
3

There's no such thing as fork() on Windows. You need to call CreateProcess() - this will start a separate process (mostly equivalent to calling fork() and then immediately exec() for the spawned process) and pass the parameters to it somehow. Since you seem to have all the data to process in a dedicated directory you can make use of lpCurrentDirectory parameter of CreateProcess() - just pass the directory path you previously used with chroot() there.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 1
    Note that `lpCurrentDirectory` corresponds to chdir(), not chroot(). – Baffe Boyois Nov 06 '09 at 10:24
  • Thanks, but this isn't exactly what I need - the main reason for using chroot is security (stops someone using ../.. in their request url to access files elsewhere on the filesystem) and setting the current directory doesn't provide this. I also have a lot of values in memory which are needed by the forked process, afaik the only way to pass these via exec would be as command-line arguments, and I don't want to go there... – codebox Nov 10 '09 at 09:13
  • 2
    Well, again there's no thing like fork() that would duplicate the process on Windows. You would have to use some form of IPC anyway so perhaps passing as a command line or through a temporary file is the easiest way. As for chroot() you can do the following: create a separate account for running the worker processes that would have no permissions except for the temporary folder and run the worker process under that account. – sharptooth Nov 10 '09 at 09:17
  • +1 to sharptooth for the suggestion of using a worker process with tighter permissions – the_mandrill Nov 10 '09 at 09:24
  • Creating processes is an expensive operation on Windows though compared to fork() or vfork() -- which is why Microsoft recommend threads. – Chris J Nov 12 '09 at 16:23
  • @Chris J: Yes, that's true. But using threads doesn't provide as much isolation. – sharptooth Nov 13 '09 at 06:21
  • @sharptooth - it depends ultimately what the OP is trying to achieve. If this is just a pet project for use by the OP only, then CreateProcess may well be fine. But if this is going to even slightly heavily used, he'd be better off looking at going down the Windows multi-threading route. If this is a learning exercise for something more complex, then again I'd suggest learning about CreateThread rather than attempting to emulate fork(). – Chris J Nov 13 '09 at 09:27
2

The absolutely simplest way of doing it is using Cygwin, the free Unix emulation layer for Windows. Download it and install a complete development environment. (Choose in the installer.) If you are lucky, you will be able to compile your program as is, no changes at all.

Of course there are downsides and some might consider this "cheating" but you asked for the simplest solution.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
1

Without using a compatibility framework (Interix, Cygwin, ...) you're looking at using the Windows paradigm for this sort of thing.

fork/vfork is a cheap operation on UNIXes, which is why it's used often compared to multi-threading. the Windows equivalent - CreateProcess() - is by comparison an expensive operation, and for this reason you should look at using threads instead, creating them with CreateThread(). There's a lot of example code out there for CreateThread().

In terms of chroot(), Windows doesn't have this concept. There's libraries out there that claim to emulate what you need. However it depends why you want to chroot in the first place.

Reading comments, if it's simply to stop people going up the tree with ../../../../(etc), chroot would do the job, but it's no substitue for parsing input in the first place and making sure it's sane: i.e., if too many parents are specified, lock the user into a known root directory. Apache almost certainly does this as I've never had to create a chroot() environment for Apache to work...

Chris J
  • 30,688
  • 6
  • 69
  • 111
0

Using fork/chroot is simply not how things are done on Windows. If you are concerned about security in subprocesses, maybe some form of virtualization or sandboxing is what you want to use. Passing complex information to the subprocess can be done by some form of RPC-solution.

It sounds to me as if you have designed your application in the Unix way, and now you want to run in on Windows without having to change anything. In that case, you may want to consider using Cygwin, but I'm not sure if/how Cygwin emulates chroot.

JesperE
  • 63,317
  • 21
  • 138
  • 197
0

Consider SUA ( aka Windows Services for Unix ). It has nearly everything you need to port applications.

man chroot(interix)

Sanjaya R
  • 6,246
  • 2
  • 17
  • 19