Uncategorized

php’s mail() in apache chroot

How to get php’s mail() function to work with mod_security chroot

The problem is that php’s mail() cannt send mail in a mod_security chroot environment. Unfortunately, you don’t see any errors and the mail just never gets sent. Let’s assume that you have setup a chroot jail for apache using mod_security (something we will document later). Let’s assume you are using /chroot/apache/ for your chroot. Here is what you need to do to make it work:

How to get php’s mail() function to work with mod_security chroot

The problem is that php’s mail() cannt send mail in a mod_security chroot environment. Unfortunately, you don’t see any errors and the mail just never gets sent. Let’s assume that you have setup a chroot jail for apache using mod_security (something we will document later). Let’s assume you are using /chroot/apache/ for your chroot. Here is what you need to do to make it work:

1. Get and compile mini_sendmail (http://www.acme.com/software/mini_sendmail/. Put the binary in /chroot/apache/usr/sbin/

2. Adjust your php.ini to use mini_sendmail. In Gentoo, you would do this:
vi /etc/php/apache2-php4/php.ini
add this:
sendmail_path = /usr/sbin/mini_sendmail -t -i

3. mini_sendmail needs a shell to execute, and it wants /bin/sh for this. So, create /chroot/apache/bin and copy /bin/sh there

4. You will probably need other libraries and files (like nsswitch.conf, passwd, etc). You can find them by using ldd and strace.
ldd /var/chroot/apache/bin/sh
# ldd sh
linux-gate.so.1 => (0xffffe000)
libdl.so.2 => /lib/libdl.so.2 (0xb7fe1000)
libc.so.6 => /lib/libc.so.6 (0xb7ed2000)
/lib/ld-linux.so.2 (0xb7feb000)

So, create a /chroot/apache/lib directory and copy needed libraries into there.
5. In our case, this still didn’t work. We needed to use strace to frigure out what was going wrong:
/etc/init.d/apache2 stop #stop apache via initscript
strace -o mytrace.1 -fF apache2 -D SSL -D PHP4 -D SECURITY #start apache with strace and log it all to mytrace.1
Now execute your test mail script and you should see which files are needed. Create the appropriate directories in your chroot and copy the missing files over.
Here is a small example of output:

14768 open("/etc/nsswitch.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
14768 open("/etc/ld.so.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
14768 open("/lib/libnss_compat.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
14768 stat64("/lib", {st_mode=S_IFDIR|0755, st_size=144, ...}) = 0
14768 open("/usr/lib/libnss_compat.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
14768 stat64("/usr/lib", 0xbfffc818) = -1 ENOENT (No such file or directory)
14768 open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
14854 open("/lib/libnsl.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
14854 open("/lib/libnsl.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
14854 stat64("/lib", {st_mode=S_IFDIR|0755, st_size=224, ...}) = 0
14854 open("/usr/lib/libnsl.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
14854 stat64("/usr/lib", 0xbfffdb18) = -1 ENOENT (No such file or directory)

6. Also you’ll need to create /dev/urandom in your chroot:
mkdir /var/chroot/apache/dev
cd to that directory
mknod -m 444 urandom c 1 8

Congrats! Your php mail() function should be working now. Let us know if you have any problems. This was a bit of a nightmare for us, so, we’d like to spare others the same nightmare.