In a PHP code I need get the values of Apache's mod_fcgid conf variables like:
FcgidMaxRequestLen
FcgidBusyScanInterval
FcgidAuthenticator
(Full list at http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html)
Is there a way I can get those values?
There's no way of getting Apache configuration directives through the PHP API, other than what's exposed by PHP itself. You would have to parse the Apache config files.
This is not trivial however, if you consider things like conditional settings and inclusion of multiple config files. It may also include security issues such as accidentally revealing config settings that can compromise your server.
Related
I want disable execute some php function like file_put_content,exec,eval on special directory.
I can use disable_functions in php.ini but how can define a special folder like c:\poject\public
If you have a working version of php.ini that disables the functions you want, then you just need to "link" the folder to that specidif .ini file. This means that your web server should, when serving files from that directory, should use that specific .ini file instead of the system one.
If you are using Apache2 as a server, a solution can be found here you can define a specific php.ini file for each virtualhost. Let's say you specific folder is /var/www/web1, you should put the php.ini with the function disabled into /var/www/web1 and use this Apache2 configuration
<VirtualHost 1.2.3.4:80>
[...]
PHPINIDir /var/www/web1
[...]
</VirtualHost>
If you are not familiar with or not using VirtualHosts (but still using Apache2), another possibile solution is putting PHP configuration into a file named .htaccess in the folder, with a syntax like this:
php_value disable_functions "file_put_content,exec,eval"
You can't use the disable_functions setting anywhere other than in a php.ini file, according to the PHP documentation,.
If you need per-vhost or per-directory restrictions on functions, I would suggest using separate instances of PHP-FPM, each of which can have its own php.ini. It also provides additional security benefits, such as complete sandboxing per daemon instance.
EDIT:
You can read about it on official documentation
or
php-fpm example configuration for both UNIX and TCP sockets.
Note: This could also fit in superuser.
I am setting up PHP 5.3.10 on a shared host with apache2 mpm itk and open_basedir in a way, that each user may not see or change the files of another user. In the apache2 vhost settings, I add the appropriate entries to restrict the user:
AssignUserId userA userA
php_admin_value open_basedir /home/userA/www/
php_admin_value upload_tmp_dir /home/userA/www/tmp/
php_admin_value session.save_path /home/userA/www/tmp/
SetEnv TMPDIR /home/userA/www/tmp/
Now, the first line sets the linux user to use for apache2, the next three lines define the basedir, upload directory and session savepath to be in the user directory. I'll get back to the last line in a sec.
Now for the problem: sys_get_temp_dir() should give back the temporary directory for php, which is /tmp be default on a linux system. For security reasons, this directory should reside in the open_basedir of userA. According to the php-source of 5.3.10, the sys_get_temp_dir()-function uses the environment variable TMPDIR to get this directory:
// php-src/main/php_open_temporary_file.c:217-219
/* On Unix use the (usual) TMPDIR environment variable. */
{
char* s = getenv("TMPDIR");
This is what the fifth line in the configuration above should do. However, sys_get_temp_dir() simply returns the global system directory, ignoring the environmental variable (which is perfectly set in $_SERVER, also viewable via phpinfo()).
This results in some nasty bugs with various software relying on sys_get_temp_dir(), as that directory is outside of the open_basedir setting. I've tried to set the variable directly into $_ENV and $_SERVER without a change in behaviour. I've tried a putenv('TMPDIR=/home/userA/www/tmp') without change.
However, I am able to change the output by defining the variable into /etc/apache2/envvars - which is useless for me, as I want each VHOST to have its own temporary folder.
The only solution I have found so far is overwriting the internal sys_get_temp_dir() through an extension like runkit and enforcing its inclusion via auto_prepend_file. But that solution is so dirty, I simply can't believe, that there is no better solution around.
So, my question: Is there any way to change the result of sys_get_temp_dir() to be set in an apache2 vhost setting, without reimplementing the function with runkit?
Edit: The apache version is 2.2.22, and I currently use mod_php. As I will have to add all users manually, an fcgi or similar setup would also be possible.
Running a putenv('TMPDIR=/foo/bar') inside PHP seems to be able to affect the result of sys_get_temp_dir(). You could have an auto_prepend_file directive arranged to run a piece of PHP to set up the TMPDIR and avoid messing with a redefinition of sys_get_temp_dir().
Edit: Also, you could easily use putenv('TMPDIR='.ini_get('open_basedir').'/tmp') to set the temporary directory to the directory structure you laid out in the question.
Funny enough, this turns out to also work (given that you keep the SetEnv TMPDIR /foo/bar in your Apache configuration):
putenv('TMPDIR='.getenv('TMPDIR'));
Seems like a no-op, but actually does have effect on sys_get_temp_dir(). I'm starting to suspect this has to be some environment-handling bug in PHP.
You have tagged your question cgi, however you are making use of
php_admin_value open_basedir /home/userA/www/
^^^^^^^^^^^^^^^
which is a setting for the apache module version of PHP, Mod_PHP. In that case PHP is loaded once the webserver starts.
Then you make use of SetEnv:
SetEnv TMPDIR /home/userA/www/tmp/
this is setting an internal environment variable. It is passed to other apache modules, however I think you need it with the request, not with the virtual server. I don't know it specifically, but I would assume according to your description that this environment variable is getting reset before the PHP script is invoked.
So more a comment than a real answer, but hopefully it helps you clarify some things.
I normally use FCGI for multi-user environments so that I can better separate the users. I never had problems with setting environment variables per each user. But that's just another comment, I don't want to say you have to use it, too. Just to highlight that you need to find out the right place within apache to set the environment variable so it is (still) set when the script is executed.
Also you might not be setting the right environment variable. According to Apache Documentation about environment variables:
Although these variables are referred to as environment variables, they are not the same as the environment variables controlled by the underlying operating system. Instead, these variables are stored and manipulated in an internal Apache structure. They only become actual operating system environment variables when they are provided to CGI scripts and Server Side Include scripts. If you wish to manipulate the operating system environment under which the server itself runs, you must use the standard environment manipulation mechanisms provided by your operating system shell.
You want to set the operating system environment variable for PHP. But you are setting the internal environment variable only.
Mod_PHP might import them to the script, so if you use getenv('TMPDIR') the PHP SAPI specific implementation is used - which does allow you to see those internal environment variables - however the php_get_temporary_directory function is not using it - it looks like.
Please add your Apache and PHP version to your question.
According to this - 4 year old - bug, sys_get_temp_dir() won't work with virtual-hosts; so
you can try to use only libraries that fixed this issue (& open a bug for those who didn't)
or append /tmp (or whatever your OS uses) in your open_basedir, as it can hold multiple directories (like include_path - separate it with ; on Windows, : otherwise)
Looking at the PHP source, sys_get_temp_dir() works with the following priority:
If its value has been calculated before, the cached value is used.
sys_temp_dir is checked in the ini configuration.
On Windows, the GetTempPathW Win32 API method is used, and according to its documentation the following are used (in this order):
The path specified by the TMP environment variable.
The path specified by the TEMP environment variable.
The path specified by the USERPROFILE environment variable.
The Windows directory.
In *nix, the following are used (in this order):
The TMPDIR environment variable.
The P_tmpdir macro
/tmp (according to the source, this is a last-ditch effort that should never happen).
That should give you enough options for controlling the result of sys_get_temp_dir (e.g. ini_set('sys_temp_dir', $tmpPath) or putenv('TMPDIR=/foo/bar') as others mentioned) Unless it was previously calculated, in which case you're SOL as far as I know and the cached value will be used (but I have zero knowledge in PHP so would love to hear otherwise).
This is a bug in php 5.2 - specify temp dir by php.ini
It's fixed in 5.5
Use this as a temporary solution:
<?php
putenv('TMPDIR=/path/to/your/tmp');
...your code here ...
In case people end up here whos Problem is not solved with putenv...
... for me, it worked to set the sys_temp_dir using php's ini_set like this:
$tmpPath = realpath(__DIR__.'/../app/tmp');
ini_set('sys_temp_dir', $tmpPath);
I am running PHP 5.5.9 (cli) on a windows8 machine.
It looks like you can change the value returned by sys_get_temp_dir(), I have just tried on apache 2.4 and php 5.6.27.
Add a sys_temp_dir in the virtualhost:
php_admin_value sys_temp_dir "/var/www/alternc/f/fser/tmp"
Restart apache, and print the value in a web page using sys_get_temp_dir():
<?php
echo sys_get_temp_dir () ;
Produces the expected output: /var/www/alternc/f/fser/tmp.
How do I edit php.ini when my host doesn't give me access to the core file? Is there a way to create a "sub" php.ini? If so, how would I make my apps pick up the subsequent file and use that instead of the master file (that I don't have access to edit)? It's a typical shared web host if that matters.
http://www.php.net/manual/en/configuration.changes.php
If your host allows it, you can use an Apache directive in an .htaccess file to override the INI path. (Most shared hosts, however, don't allow this.)
You might also be able to change certain individual settings via the ini_set() function in your script - again, if your host allows it.
Try to use the built-in function ini_set().
anyone knows if is it possible to enable php parse_ini_file() function overriding php.ini settings into .htaccess? If yes how it can be done?
Thank you all for help
If it was disabled using disable_functions, you can't reactivate it using a .htaccess php_value directive. See http://php.net/manual/en/ini.core.php
As far as I know, parse_ini_file() is a core function built into PHP, thus it can't really be enabled. I'll guess that you are facing one of these situations:
Your host has disabled it for security reasons (:-?) using the disable_functions directive.
You are providing a URL in the $filename parameter and your host has disabled loading or remote files with the allow_url_fopen directive.
You are reading an *.ini file you don't have access to.
In general, all three cases imply that you are just not allowed to do so. Even if you manage to find a hack and override the restriction, you might be violating your host's terms of use. Whatever, it's possible that you are just trying to do the wrong thing:
Local files can be read from disc, there is not need to use HTTP.
You should be able to read your own files, given that they're given the appropriate permissions.
I added a copy of php.ini under the folder where application wants to call parse_ini_file() and it helped, but my hosting provider "honors" php.ini file per directory, so each app can use different settings.
In this case the app was complaining PHP function parse_ini_file is not available not because the method was disabled, but because it could not find php.ini to parse.
I'm just curious if there's a way to disable things like shell_exec() using the .htaccess file or something, not globally, but only for specific subdomains or directories (possibly disable fopen() on files above the subdir). It occurred to me that on one of my shared hosts where I'm sharing subdomain space with a friend he could use PHP to get a look at directories outside his own.
Perhaps I could use mod_rewrite and send any hit anywhere through a PHP script that disables certain things before forwarding the request to where it was going? Would this work, and would it incur a significant performance penalty?
You can do it programmatically:
ini_set('disable_functions', 'fopen,shell_exec');
or in .htaccess:
php_value disable_functions fopen,shell_exec
There shouldn't be any performance degradation. I doubt you'll be changing the settings repeatedly inside a for(), while() or foreach() loop.
You can do this with a .htaccess file:
http://www.askapache.com/php/custom-phpini-tips-and-tricks.html#m0-askapache12
I believe those things need to be changed in the php.ini file. Some host allow you to have multiple php.ini files within the files structure. If you are on a shared hosting environment then you probably will have one php.ini file for all shared accounts. Host realize this is a problem so they allow you to have your own within your home directory for sub directory... check with your host.