LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   get php to write files to www-data owned directory (https://www.linuxquestions.org/questions/programming-9/get-php-to-write-files-to-www-data-owned-directory-4175609990/)

pizzipie 07-16-2017 08:16 PM

get php to write files to www-data owned directory
 
Just learned that php files written under control of browser (firefox) and apache2 are owned by www-data. I created a folder on my desktop named "PhotoTransFiles" to copy images into.

Permission Info: # file: Desktop/PhotoTransFiles/
# owner: rick
# group: www-data
user::rwx
user:www-data:rwx
group::rwx
mask::rwx
other::---

This allows PHP to make a directory "xxx" to contain my photos. All ok.

However, when the PHP script runs and creates a new directory "xxx/yyy"
the "yyy" directory is now owned by www-data and will not allow photo files to be copied to it.

I added user "rick" to the www-data group:
www-data:x:33:rick, but didn't do the trick.

I tried changing the /var/www/html permissions as follows:
# file: var/www/html
# owner: www-data
# group: root
user::rwx
user:rick:rwx <========== I added
group::r-x
group:rick:rwx <========= I added
mask::rwx
other::rwx <========== I added

I am using a virtual host "mydb.com". I don't know whether this complicates this or not??

Obviously I don't know what I'm doing and need help in fixing this!!

Thanks in advance for any help.

R

j-ray 07-17-2017 03:37 AM

you could change permissions of the new created directory using chmod funcion,
http://php.net/manual/en/function.chmod.php
after that you can copy the images.
cheers
j

NevemTeve 07-17-2017 06:34 AM

On the other hand, you cannot change ownership; if your process is running as 'www-data', the owner will be 'www-data'; if it is running as 'rick', the owner will be 'rick'.

Still, setgid directories might be of use.
Code:

mkdir /somepath/fotodir
chgrp fotogroup /somepath/fotodir
chmod g+rwxs /somepath/fotodir
adduser rick fotogroup
adduser www-data fotogroup

After this, both 'rick' and 'www-data' can create files/subdirectories in /somepath/fotodir; the group of those will be 'fotogroup'. If they use chmod 0775 (for directories) /0664 (for files), then they will be able to write each others files.

astrogeek 07-17-2017 05:27 PM

As noted in your original thread, the problem is due to the different runtime contexts of apache and php, and your login user performing shell operations.

You are moving onto the right track now, but you still need to try to understand why that difference of context exists and why it is important, and work with it instead of trying to force it to just do what you think you want.

Quote:

Originally Posted by pizzipie (Post 5735802)
Just learned that php files written under control of browser (firefox) and apache2 are owned by www-data. I created a folder on my desktop named "PhotoTransFiles" to copy images into.

That was discussed in the other thread, too.

The apache server (httpd) and the php processes invoked by it receive data and commands from the big evil external world which can be extremely dangerous to your system! Therefore, by design, they typically run as a special non-privileged user, www-data in your case. That user account usually has no login shell, has access to files on a strictly limited path (usually called the server root) and is denied access to anything outside the server root directory path. That is, it is all designed to run isolated in most ways from your system.

So ANY files uploaded or written by php, and the directories they are written to, must be owned by and/or writeable by the web server user, www-data. The whole thing is designed to enforce that isolation and is a basic principle which differentiates Unix-like operating systems from others. Never try to circumvent it, especially by the often offered suggestion to set file permissions to 777, as also mentioned in your other thread!

Now, although apache, and its php processes run as user www-data on the server, that user identifier and indeed, the whole concept of system user identifiers, does not extend to the client browser! The browser, via http request, has no knowledge of, nor access to system level information, users, permissions - NADA! And the http server has zero knowledge of that same information on the client - even when they are running on the same machine! All for a very long list of very good reasons, and all by usually careful design!

And this is the point at which you confuse yourself and run into conflict with your system's design when trying to use the httpd server (apache and php, etc.) as just another local application.

Local user rick writes a php program to do something useful, opens his browser and tries to use his local apache server to manage local files in his local home directory, and runs headlong into permission problems! Why? Because while he knows who he is, the browser/http process is all designed to NOT know nor care who he is!

In order to configure it all to work for him, on his local server with his local files, he must recognize all of this and configure his http server to work on his local files anyway, without knowing, or caring that the browser is being driven by the same human.

The first requirement then, is that the http server must be configured with a server root path which it either owns or to which it has write permission. Usually this is below /var/www/htdocs or something similar, and will usually have owner/group set as www-data:www-data.

The next requirement is that local login user rick must also have write permission to this same path in order to save photos to the directories managed by the http server (user www-data).

As there can be only one owner for any file path, the shared access is usually allowed by having both users be members of a common group. Usually this is the web server user group, or www-data.

Then, in order to allow local user rick to have full shell access to that same path, he would be made the owner of the file path and added to the www-data group. He can either set www-data as his default group (man usermod, -g), or he may use the setgid flag on that directory path as mentioned previously.

Assuming the desired file path to be /home/rick/public_html/... the primary configuration parameters for this setup might look like this (adjust for your system's actual paths!):

Code:

Create symlink path
/var/www/htdocs/rick -> /home/rick/public_html

Virtual host config
DocumentRoot /var/www/htdocs/rick

Server Path
lrwxrwxr-x 1 rick www-data 25 Jun 24  2017 /home/rick/public_html

Set default login group for rick
usermod -g www-data rick

OR

Add rick to www-data but not as default

usermod -a -G www-data rick

Set ownership of web root in rick's home
chown rick:www-data /home/rick/public_html
chmod g+s /home/rick/public_html

Now, there are variations among distros for default paths and permissions for the web server, so your actual mileage may vary. But for all the above conditions must be met is some way or another for this to work. And this is not the only way (or even the best way) to provide the desired level of function, but it is the path you are on so let's try to reach the end.

My main point is to try to move you past the misleading perspective of "Why can't firefox do this?", to a more complete understanding of the complete problem, at which point you can ask, and hopefully answer the right questions!

If you need additional help, please post your virtual host configuration along with the actual long listing (ls -l) of the various paths.

I am going to leave both threads open so as not to confuse the replies already received, but in future please do not open new threads for the same subject. That will make it much easier for you and us to follow the discussion and make the information more easily accessible to future visitors with similar problems.

pizzipie 07-27-2017 01:37 PM

astrogeek, thanks very much for your extensive explanation of this. I have been not been able to follow this up for the past 10 days as I was traveling. I will do so now. Below are the settings that exist right now without me trying to change permissions to reflect your latest text. I realize some of the 777 permissions are not what I want so will change them when I get this thing to work properly.

Quote:

If you need additional help, please post your virtual host configuration along with the actual long listing (ls -l) of the various paths.
VIRTUAL HOST: mydb.com.conf

Code:

<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.

        ServerName mydb.com
        ServerAlias www.mydb.com
        ServerAdmin admin@mydb.com
        DocumentRoot /home/rick/DB-Web

<Directory  /home/rick/DB-Web>
 Options Indexes FollowSymLinks
        Require all granted
</Directory>


        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet


PATHS & PERMISSIONS

rick@rick-Latitude-E6510:~$ ll

drwxr-xr-x 33 rick rick 4096 Jul 19 06:37 ./
drwxr-xr-x 3 root root 4096 May 25 19:46 ../
drwxrwxrwx 31 rick rick 4096 Jul 1 13:31 DB-Web/ <==== Document Root - all my web programs in here


rick@rick-Latitude-E6510:~/Desktop$ ll

drwxrwx---+ 3 rick www-data 4096 Jul 17 16:50 PhotoTransFiles/

rick@rick-Latitude-E6510:~/Desktop/PhotoTransFiles$ ll

drwxr-xr-x 2 www-data www-data 4096 Jul 27 10:21 2017Jul27-10:21_DCIM/

This file was created by my PHP script - Photo Images to be copied here. Thinking that I should add 'rick' to the 'www-data' group with rw- permissions.

rick@rick-Latitude-E6510:/var/www$ ll

drwxrwxrwx+ 2 www-data root 4096 Jun 8 17:17 html/


USERS & GROUPS

rick@rick-Latitude-E6510:~$ id rick

uid=1000(rick) gid=1000(rick) groups=1000(rick),4(adm),24(cdrom),27(sudo),30(dip),
33(www-data),46(plugdev),113(lpadmin),129(sambashare)

rick@rick-Latitude-E6510:~$ id www-data

uid=33(www-data) gid=33(www-data) groups=33(www-data)

astrogeek 07-27-2017 11:32 PM

Welcome back!

OK, we are part way there. I am a little pressed for time so I'll keep things a bit short tonight, but hopefully sufficient to advance the cause...

I see user rick is a member of www-data group... that should be OK.

You still do not have your vhost DocumentRoot below the server root. If you look in your httpd.conf (or whatever it is named on your distro), you will find a DocumentRoot which is probably /var/www/html going by the paths shown. The path by which apache must find everything, and from which your vhost DocumentRoot inherits a good many properties.

As I indicated in my previous post, one way to do that is to create a symlink in the server root to your vhost directory, something like this...

Code:

cd /var/www/html
ln -s /home/rick/DB-Web DB-Web

And

chown rick:www-data /home/rick/DB-Web
chmod 755 /home/rick/DB-Web
chmod g+s /home/rick/DB-Web

...using your indicated path.

Then in the vhost file, set...

Code:

DocumentRoot /var/www/html/DB-Web
Also, reset the permissions on /var/www/html to 755 while we are at it.

Be sure to check the master apache conf though, and use the same prefix directories used there for all that, then restart apache after those changes.

The end result is that apache finds your vhost directory along its root path, with acceptable ownership and permissions at every subdirectory. In other words, even though it is going to the same place, it matters how it gets there - all paths are NOT the same!

Code:

/var/www/html/DB-Web/... (GOOD! Apache can rwx every directory along the way...)

NOT

/home/rick/DB-Web/... (BAD! Apache cannot rwx any parent directories, so it cannot rwx the subdirectory!)

Check that this works as far as serving pages and allowing rick to edit content below the DB-Web/ path... maybe set up a test php file, echo "HelloRick!". That should give you a working rick-accessible web server.

AFTER that part is working, we need to look at the paths to your transfer directory.

Code:

~/Desktop/PhotoTransFiles/2017Jul27-10:21_DCIM
I see you made it with group ID www-data... but that doesn't matter - the web server cannot see outside the DocumentRoot which is ~/DB-Web! You can't stretch it that way.

So for the web sever to be able to read/write to the transfer directory, it must also be reachable under the vhost DocumentRoot path. You might want to move it there, or you could create a symlink to it from the DB-Web directory, and use the setgid flag so that whatever is written the from a shell, or non-web server process, will be accessible to the web server.

Out of time! Let me know how that works!

pizzipie 07-28-2017 03:14 PM

Here is the current information.

All my other programs in DB-Web work as before. The most significant happening is that my PHP script will not create the directory to contain the photos in PhotoTransFiles (now residing in the DB-Web directory).


VIRTUAL HOST: mydb.com.conf
Code:


<VirtualHost *:80>

        ServerName mydb.com
        ServerAlias www.mydb.com
        ServerAdmin admin@mydb.com
        DocumentRoot  /var/www/html/DB-Web


<Directory  /var/www/html/DB-Web >
 Options Indexes FollowSymLinks
        Require all granted
</Directory>


        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined


</VirtualHost>

PATHS & PERMISSIONS

rick@rick-Latitude-E6510:~$ ll

drwxr-xr-x 33 rick www-data 4096 Jul 27 14:54 ./
drwxr-xr-x 3 root root 4096 May 25 19:46 ../
drwxr-sr-x 32 rick www-data 4096 Jul 28 10:36 DB-Web/

rick@rick-Latitude-E6510:~/DB-Web$ ll

drwxr-sr-x 32 rick www-data 4096 Jul 28 10:36 ./
drwxr-xr-x 33 rick www-data 4096 Jul 27 14:54 ../
drwxr-sr-x+ 3 rick www-data 4096 Jul 28 12:07 PhotoTransFiles/ <===== moved from Desktop


rick@rick-Latitude-E6510:/var/www$ ll

drwxr-xr-x 3 root root 4096 May 29 13:29 ./
drwxr-xr-x 15 root root 4096 May 29 13:29 ../
drwxr-xr-x+ 2 www-data root 4096 Jul 28 09:18 html/


rick@rick-Latitude-E6510:/var/www/html$ ll

drwxr-xr-x+ 2 www-data root 4096 Jul 28 09:18 ./
drwxr-xr-x 3 root root 4096 May 29 13:29 ../
lrwxrwxrwx 1 rick rick 17 Jul 28 09:18 DB-Web -> /home/rick/DB-Web/


USERS & GROUPS

rick@rick-Latitude-E6510:~$ id rick

uid=1000(rick) gid=33(www-data) groups=33(www-data),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),129(sambashare)

rick@rick-Latitude-E6510:~$ id www-data

uid=33(www-data) gid=1000(rick) groups=1000(rick)

astrogeek 07-28-2017 03:49 PM

Pay attention to the ownerships and permissions along the entire path...

Code:

rick@rick-Latitude-E6510:~$ ll

drwxr-xr-x 33 rick www-data 4096 Jul 27 14:54 ./
drwxr-xr-x 3 root root 4096 May 25 19:46 ../
drwxr-sr-x 32 rick www-data 4096 Jul 28 10:36 DB-Web/

rick@rick-Latitude-E6510:~/DB-Web$ ll

drwxr-sr-x 32 rick www-data 4096 Jul 28 10:36 ./
drwxr-xr-x 33 rick www-data 4096 Jul 27 14:54 ../
drwxr-sr-x+ 3 rick www-data 4096 Jul 28 12:07 PhotoTransFiles/

The group has no write permission for those.

Code:

rick@rick-Latitude-E6510:/var/www/html$ ll

drwxr-xr-x+ 2 www-data root 4096 Jul 28 09:18 ./
drwxr-xr-x 3 root root 4096 May 29 13:29 ../
lrwxrwxrwx 1 rick rick 17 Jul 28 09:18 DB-Web -> /home/rick/DB-Web/

WHy does rick own that?

I am not sure about /var/www/html, whether that should be root:root or www-data:www-data, but www-data:root looks wrong (I'd set those to the distro defaults).

pizzipie 07-30-2017 10:03 PM

I am going crazy!!!!!!!!!

Finally got back to being able to create Image directories under /home/rick/DB-Web/PhotoTransFiles, one of which is /2017Jul30-19:35_102CANON/ ($dest).

I think that these are permissions for the full path.

drwxr-xr-x+ 2 www-data www-data 4096 Jul 30 17:36 html/

lrwxrwxrwx 1 www-data www-data 17 Jul 30 17:36 DB-Web -> /home/rick/DB-Web/

drwxr-sr-x 32 rick www-data 4096 Jul 30 18:44 DB-Web/ <=== also tried www-data www-data

drwxrwsr-x+ 10 rick rick 4096 Jul 30 19:35 PhotoTransFiles/

drwxr-sr-x 2 www-data rick 4096 Jul 30 19:35 2017Jul30-19:35_102CANON/

Code:

        copy($imgFile, "/home/rick/DB-Web/PhotoTransFiles/".$dest);
produces this error:

PHP Warning: copy(IMG_8646.JPG): failed to open stream: No such file or directory in /home/rick/DB-Web/foolaround/trantest.php on line 162, referer: http://mydb.com/foolaround/tree3.html

I can't see where the permissions are wrong.

NevemTeve 07-30-2017 11:33 PM

Add this line before copy:
Code:

system (sprintf ("ls -ld -- '%s' '%s' '%s'",
    $imgFile, "/home/rick/DB-Web/PhotoTransFiles/", "/home/rick/DB-Web/PhotoTransFiles/".$dest));


sundialsvcs 07-31-2017 08:18 AM

Probably the most-efficient way to handle this sort of requirement is with Access Control Lists (ACLs), which allow you to craft very-specific extensions to (or, overrides of) the "traditional Unix permissions-mask."

Note that ACLs can get a bit interesting when network file systems of any sort are involved.

NevemTeve 07-31-2017 09:41 AM

(they don't solve "No such file or directory" errors, though)

astrogeek 07-31-2017 05:31 PM

I think you are making this more difficult for yourself than it should be.

You do not see anything wrong with this after all that has been said to this point?

Code:

drwxrwsr-x+ 10 rick rick 4096 Jul 30 19:35 PhotoTransFiles/ (group?)

drwxr-sr-x 2 www-data rick 4096 Jul 30 19:35 2017Jul30-19:35_102CANON/ (owner <-> group)



QUIT just trying things, and very simply set the ownerships and permissions, once. If things still do not work, read the error messages - it may not be the same error (and does not appear to be in this case)!

As NevemTeve has indicated, the problem now is "No such file or directory". You need to understand what file or directory it is referring to.

My guess is that you are using an HTML file select element to pick a file to be moved. If so, you need to understand how those work - they do not include the file's path - only the file name. So unless IMG_8646.JPG happens to be located in the same place as trantest.php, it will not be found.

Please post the output of the line NevemTeve has suggested, along with the location of the image file, and tell us how you are selecting those files for copy.

sundialsvcs 08-01-2017 08:43 AM

Quote:

Originally Posted by NevemTeve (Post 5742122)
(they don't solve "No such file or directory" errors, though)

This is true, but they would allow the web-site user to create that file or directory as needed, if the ACL permissions allow.

Also, note that the Apache user in this case should not run as nobody. It should run as a user/group which cannot be directly logged-on to, and this user/group should be assigned to no other purpose. (This is, of course, the default arrangement.)

pizzipie 08-01-2017 12:07 PM

1 Attachment(s)
Code:


drwxrwsr-x+  3 rick www-data  4096 Jul 31 10:48 PhotoTransFiles/

drwxr-sr-x  2 www-data www-data 4096 Aug  1 09:08 2017Aug01-9:08_102CANON/

drwxr-sr-x 2 www-data rick 4096 Jul 30 19:35 2017Jul30-19:35_102CANON/ (owner <-> group)

I created the File PhotoTransFiles with the (owner <-> group) shown above.

The File 2017Aug01-9:08_102CANON/ was created by the program with the (owner <-> group) shown above.

Quote:

Please post the output of the line NevemTeve has suggested, along with the location of the image file, and tell us how you are selecting those files for copy.
There are 98 images so I cut off the full output (see thumbnail)


Code:



function copyPhotos($src, $dest) {
       
global $src;
global $dest;

echo "\n".getcwd();
echo "\n\nsrc  $src ... dest /home/rick/DB-Web/PhotoTransFiles/$dest\n\n";

        $dh=opendir($src);
                while(false != ($imgFile=readdir($dh))) {
                        if($imgFile != "." && $imgFile != "..") {                       
                            echo $imgFile."\n";
                          $str="/home/rick/DB-Web/PhotoTransFiles/$dest\n";       
       

       
Quote:

       
       
               
       
       

                       

                       
                                NevemTeve        Add this line before copy:
                       
                       

               

        system (sprintf ("ls -ld -- '%s' '%s' '%s'",
    $imgFile, "/home/rick/DB-Web/PhotoTransFiles/", "/home/rick/DB-Web/PhotoTransFiles ".$dest));               
                                       
                                copy($imgFile,$str );
       
                        }       
                } // while       
        echo "\n===============  $dest  =====================\n";
} // funct copyPhotos


NevemTeve 08-01-2017 12:35 PM

It would be something like this:
Code:

    $dh=opendir($src);
    while ($imgFile=readdir($dh)) {
        if ($imgFile == "." || $imgFile == "..") continue;
        $imgPath= $src.'/'.$imgFile;       
        if (! is_file ($imgPath)) continue;

        $destPath= "/home/rick/DB-Web/PhotoTransFiles/$dest\n";       
        copy ($imgPath, $destPath);
    }
    closedir($dh);


sundialsvcs 08-02-2017 08:04 AM

I'm never too thrilled with the idea of web-pages writing anything into anyone's home-directory. I suggest that you should designate one single directory – e.g. a root-level directory, possibly then subdivided – as being "the (only) place that web-page code can write to." If you need to move the file somewhere else, feel free, but "that's the one-and-only place to go looking for it."

This also simplifies permissions and helps avoid accidental compromise of "home directories." (The more elaborate you make things, the more likely it is that you'll screw something up and not realize it. ;)) This clearly-distinct strategy also further ensures that "relative pathnames" won't bring surprises. (Use tools like AppArmor to ensure that Apache can't get out-of-bounds.)

"A place for everything, and everything in its place."

pizzipie 08-08-2017 02:28 PM

Thank you all very much for trying to help me with this.

I can't get it to work my way so will go back to where I started which was a completely command line implementation of the program run in PHP. I just wanted the eye candy appeal of the browser but didn't realize the security risks etc. that you all pointed out.

Thanks again for all your time,

R

astrogeek 08-09-2017 01:27 AM

You are welcome, and sorry that didn't work out as you wanted.

I hope that you learned the reasons why using Apache as a system level application is sometimes problematic, which will help you with future uses.

As I have looked over this thread once more, it occurred to me that PHP really is a good general purpose scripting language, and that the problems that you experienced result mainly from the way Apache is designed to work. But as you have some familiarity with PHP it may be possible for you to use your PHP code with one of the GUI binding libraries available which would eliminate the Apache complications.

Two come to mind, wxPhp and PHP-Gtk, but there are others. You might give those a look and see if they would allow you to build a GUI front using PHP, but with the eye-candy you desire.

Thanks for returning and marking this thread solved and good luck!


All times are GMT -5. The time now is 11:33 AM.