Since moving from cookie to session-based authentication, I’ve been getting permission errors from my PHP5 application (Outage Management System).
Notice: session_start() [function.session-start]:
ps_files_cleanup_dir: opendir(/var/lib/php5) failed: Permission
denied (13) in <path> on line <line number>
And then there’s the 24 minutes timeout even though my .htaccess’ properly setup and configured. Both of these issues prompted me to dig deeper into Ubuntu-specific PHP5 configuration.
I googled the error and confirmed that only Debian-based distributions are affected.
The default setup is to save the session files (and maybe cookies though I’m unsure) to /var/lib/php5 while a cron script is placed at /etc/cron.d/php5 to clear out the said session files based on /etc/php5/apache2/php.ini‘s session.gc_maxlifetime setting (defaults to 1440 seconds or 24 minutes).
This has resulted into two things:
- The 24 minutes timeout is enforced regardless of your .htaccess’ session.gc_maxlifetime settings
- The session_start() error show above would show up once every 100 hits
The /etc/cron.d/php5 script would only read the gc_maxlifetime values from the global php.ini file. It does not have the capability to locate all .htaccess on your system. Session files are also stored on one location, and if the php5 cron script runs, it’ll delete every single one of them forcing your users to re-authenticate on all your PHP applications.
The files on /var/lib/php5 could only be accessed and modified by the cron script running as root while the www-data group would only be able to write/save the session files. Thus, PHP5 will not be able to run its own garbage collection resulting to the permission denied error.
Based on the bug reports     I stumbled upon relating to the issue I’m experiencing, the configuration was designed to secure the server. Placing session files on a directory where only the cron script running as root can have access to prevents other www-data users from sniffing out sessions.
What does having different paths per SAPI buy you? The reason we did it this way in the first place (setting gc to 0, strict/sticky permissions, and a cronjob) was so that users all running as the same user (say, all www-data) couldn’t sniff each other’s session.
What confuses me the most is this issue isn’t documented anywhere on the Community Pages nor on the Server Guide considering most Web Developers I know uses Ubuntu. Heck, it’s not even documented on the man page.
Oscar Merida proposed this issue be documented on the most obvious location – the php.ini file.
The comments around session.gc_divisor should be amended to make sys admins aware of this. Something along the lines of:
; This is disabled in the Debian packages, due to the strict permissions
; on /var/lib/php5. Instead of setting this here, see the cronjob at
; /etc/cron.d/php5, which uses the session.gc_maxlifetime setting below
; If your php scripts use their own session.save_path, either make sure they
; enable garbage collection by setting session.gc_probability or globally
; enable it here.
The bug was closed as fixed, but I don’t know where it is on Maverick.
I never modify php.ini, and instead rely on .htaccess. Not only is it bad practice for developers to do so, but you’ll never find a shared host that’ll allow you to modify the configuration file… ever! And please no self-host your server arguments. Not everyone can afford nor is capable of this, Software Development does not equate to System Administration.
My solution is set a different save path on .htaccess. And create a crontab script to clear the sessions. It may not conform to the php5 maintainers’ definition of secure, but at least I can get around those issues:
php_value session.gc_maxlifetime 604800
php_value session.cookie_lifetime 604800
php_value session.cache_expire 604800
php_value session.gc_divisor 100
php_value session.gc_probability 1
php_value session.save_path /srv/oms/tmp