DISABLE ADBLOCK

ADBlock is blocking some content on the site

ADBlock errore

How to force PHP set correct permissions on files uploading?

StackOverflow https://stackoverflow.com/questions/14281100

Question

I have server with FreeBSD 8.0, Apache 2.2.23 and PHP 5.4.10. That is my VirtualHost config:

<VirtualHost *>
    ServerName site.com
    ServerAlias www.site.com
    DocumentRoot /usr/home/site/pub/htdocs/
    php_admin_value open_basedir /usr/home/site/
    php_admin_value session.save_path 0;0660;/usr/home/site/pub/tmp/
    php_admin_value upload_tmp_dir /usr/home/site/pub/tmp/
</VirtualHost>

/usr/home/site/pub/tmp/ owned by site:www with 4770 permission. Session files creating correctly (660 and site:www). But uploaded temporary files creating with 600 in permissions. So, because this temporary file owned by site:www and Apache running from www:www, move_uploaded_file() cannot move file.

How to fix it?

I think that I need patch PHP for force set permission on this tmp file. But where? And which internal function in PHP can to do it?

Solution 4

I've find the way to fix it. That is code of my patch:

*** main/php_open_temporary_file.c.orig 2013-01-11 20:33:42.000000000 +0400
--- main/php_open_temporary_file.c  2013-01-11 21:17:44.000000000 +0400
***************
*** 101,113 ****
    char cwd[MAXPATHLEN];
    cwd_state new_state;
    int fd = -1;
! #ifndef HAVE_MKSTEMP
!   int open_flags = O_CREAT | O_TRUNC | O_RDWR
! #ifdef PHP_WIN32
!       | _O_BINARY
! #endif
!       ;
! #endif

    if (!path || !path[0]) {
        return -1;
--- 101,107 ----
    char cwd[MAXPATHLEN];
    cwd_state new_state;
    int fd = -1;
!   int open_flags = O_CREAT | O_TRUNC | O_RDWR;

    if (!path || !path[0]) {
        return -1;
***************
*** 144,169 ****
        return -1;
    }

- #ifdef PHP_WIN32
- 
-   if (GetTempFileName(new_state.cwd, pfx, 0, opened_path)) {
-       /* Some versions of windows set the temp file to be read-only,
-        * which means that opening it will fail... */
-       if (VCWD_CHMOD(opened_path, 0600)) {
-           efree(opened_path);
-           free(new_state.cwd);
-           return -1;
-       }
-       fd = VCWD_OPEN_MODE(opened_path, open_flags, 0600);
-   }
- 
- #elif defined(HAVE_MKSTEMP)
-   fd = mkstemp(opened_path);
- #else
    if (mktemp(opened_path)) {
!       fd = VCWD_OPEN(opened_path, open_flags);
    }
- #endif

    if (fd == -1 || !opened_path_p) {
        efree(opened_path);
--- 138,146 ----
        return -1;
    }

    if (mktemp(opened_path)) {
!       fd = VCWD_OPEN_MODE(opened_path, open_flags, 0660);
    }

    if (fd == -1 || !opened_path_p) {
        efree(opened_path);

Now it working fine, but show the warning "Warning: move_uploaded_file(): Operation not permitted in /path/to/script.php on line 111". How to suppress this warning - I don't know.

OTHER TIPS

Create the file and then set the permission would work.

chmod("/somedir/yourfile", 0644);

Don't downvote peole who are telling you to use chmod() because that is the only solution to change file permissions from PHP. However, the main problem appears to be that either Apache is creating the files with a different uid than what the script is running as, [not likely AFAIK] or you're trying to modify files that were created using a different process running as a different user.

Only the owner of the file can change permission/ownership on a file, and unless a separate process ran specifically to transfer ownership to another uid the owner of the file is the uid that created it.

Once again, chmod() and chown() are the only two methods by which you can change permissions and ownership, and are equivalent to issuing the shell commands via exec().

Try looking at chown you can change the owner of the file temporarily so you can make appropriate changes:

$File = '/path/to/file';
chown($File, USERNAMEPHPISRUNNIGNAT);
chmod($File, 0644);
// Makes Appropriate changes To Files 
chown($File, originalowner);
// Changes your file back to it's original owner

Want to find out what username php is running as:

echo exec('whoami');

The above will return the user which php is running as.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow