I have a dedicated server with tens of virtual hosts. I want to determine what file is calling mail() function and log this globally. I need something like that:
[Wed Feb 13 10:42:39 2013] mail() called from /var/www/example1.php on line 70 [Wed Feb 13 10:42:40 2013] mail() called from /var/www/example2.php on line 70
I can’t use debug_backtrace() or similar because I can’t add this to any PHP file in the server. Can I log all function calls globally in a file like errors are logged to a file like error.log?
In general, you are going to have trouble with this; PHP doesn’t provide a logging mechanism built-in, so you’ll need to add something to your PHP system to do it.
The options as I see it:
Modify the PHP code. Given what you’ve said in the question, I guess this isn’t an option, but it needs to be stated, as it is the obvious answer. (PHP’s
mail()function is so basic that anyone writing PHP code really ought to be using a wrapper class for it anyway just to retain their sanity)
If we’re talking specifically about the
mail()function, then we could log it by logging the sendmail client that
sendmailsystem on the server is probably controlled by a unix shell script that is called by PHP’s
mail()function. You should be able to modify this shell script to log the mail events. This probably won’t be able to give you details like the line number, but it will tell you the user that is doing it, etc.
Use the Suhosin PHP hardening patch. This is a patch for PHP that provides dozens of security-related features; I would strongly recommend it for a shared hosting environment anyway. But for you it also includes logging features, which may allow you to log usage of particular functions, including filename and line number — ie exactly the scenario you’re looking for. This is the solution I’d recommend …. the only big problem you’ll have here is if you’ve kept your PHP version bang up to date, because Suhosin is currently only available for PHP 5.3, not 5.4. As a PHP developer, I would be pushing to get PHP 5.4 on my server, but as a provider, 5.3 is still supported, so there’s nothing wrong with it. (on the flip side, if you are still on 5.2 you should be upgrading ASAP, as it’s been unsupported for years and has known security holes).
As of >= PHP 5.3.0, you can simply specify a path to the desired location of your logilfe in your
mail.log = /path/to/some/logfile
See the PHP docs for details.
What you can do is, download php source code, edit this file:
and add logger there.
That’s probably only way you can implicitly debug who’s calling your php function from where.
To block mail() just delete /usr/sbin/sendmail from php’s chroot and force authenticated smtp.