2

I'm using Ubuntu server and I have a cgi-bin script doing the following . . .

#!/bin/bash
echo Content-type: text/plain
echo ""
cat /home/user/.program/logs/file.log | tail -400  | col -b > /tmp/o.txt
cat /tmp/o.txt

Now if I run this script with I am "su" the script fills o.txt and then the host.com/cgi-bin/script runs but only shows up to the point I last ran it from the CLI

My apache error log is showing "permission denied" errors. So I know the user apache is running under somehow cannot cat this file. I tried using chown to no avail. Since this file is in a user directory, what is the best way to either duplicate it or symbolic link it or what?

I even considered running the script as root in a crontab to sort of "update" the file in /tmp/ but that did not work for me. How would somebody experienced with cgi-bin handle access to a file in a users directory?

tripleee
  • 175,061
  • 34
  • 275
  • 318
Matt3324
  • 21
  • 2
  • Running `tail -n 400 logfile | sudo -u www-data tee /var/www/tail.txt >/dev/null` once per minute would obviate the need for a CGI script in the first place. – tripleee Mar 13 '14 at 18:41

2 Answers2

3

The Apache user www-data does not have write access to a temporary file owned by another user.

But in this particular case, no temporary file is required.

tail -n 400 logfile | col -b

However, if Apache is running in a restricted chroot, it also has no access to /home.

The log file needs to be chmod o+r and all directories leading down to it should be chmod o+x. Make sure you understand the implications of this! If the user has a reason to want to prevent access to an intermediate directory, having read access to the file itself will not suffice. (Making something have www-data as its group owner is possible in theory, but impractical and pointless, as anybody who finds the CGI script will have access to the file anyway.)

More generally, if you do need a temporary file, the simple fix (not even workaround) is to generate a unique temporary file name, and remove it afterwards.

temp=$(mktemp -t cgi.XXXXXXXX) || exit $?
trap 'rm -f "$temp"' 0
trap 'exit 127' 1 2 15

tail -n 400 logfile | col -b >"$temp"

The first trap makes sure the file is removed when the script terminates. The second makes sure the first trap runs if the script is interrupted or killed.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • I tried using just tail by itself and here is the new error in my apache error log tail: cannot open `/home/user/.program/log' for reading: Permission denied – Matt3324 Mar 13 '14 at 18:24
  • The signal numbers in `trap` should properly be symbolic. Too old and lazy to look them up. EXIT and ... something anf HUP and INT I guess? – tripleee Mar 13 '14 at 18:26
  • Does the user know and approve of this? Then getting permissions granted and/or the file moved to a more accessible location should be a simple matter. – tripleee Mar 13 '14 at 18:28
  • yes the user is my user, the file is a log created by a program in userland that should not be run as root. Is there an easy way to copy that file live as it grows to a location apache can access? I was thinking crontab but you may know an easier way. – Matt3324 Mar 13 '14 at 18:34
  • Having the file in a sane place to begin with is probably better. Note the recent update re: permissions on directories. – tripleee Mar 13 '14 at 18:36
  • You did it , I have no idea what the o+r and o+x do but I will read up on it. I thought having chmod 777 would suffice but I guess not. – Matt3324 Mar 13 '14 at 18:42
  • You know it is producing something now but it is actually an old part of the log and when the log updates and i refresh the page the page stays the same. I have no idea. – Matt3324 Mar 13 '14 at 18:44
  • I am the only user on the server, just root and my user, is chmod 777 still a bad idea? – Matt3324 Mar 13 '14 at 18:46
  • Ok so this actually works but only once, then every time i go to update the page it only loads the original cat of the log, it won't repeat the process. I have no idea why. – Matt3324 Mar 13 '14 at 19:12
2

I would be inclined to change the program that creates the log in the first place and write it to some place visible to Apache - maybe through symbolic links.

For example:

ln -s /var/www/cgi-bin/logs /home/user/.program/logs

So your program continues to write to /home/user/.program/logs but the data actually lands in /var/www/cgi-bin/logs where Apache can read it.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • If the final destination is not permitted, Apache will not be able to traverse the symlink, either. Otherwise it would be trivial to obtain access to stuff you are blocked from! – tripleee Mar 13 '14 at 18:44
  • Apache doesn't need to use the symlink. The OP's original program writes via the symlink, Apache reads the real file. Sorry, I had the link back-to-front. – Mark Setchell Mar 13 '14 at 18:46
  • symbolic links make sense to me, i thought that might be the way, I ran the equiv of the logic on my system but ln said "failed to create, file exists." Sorry I have no idea, sometimes the cgi script runs btw . . . I am confused. – Matt3324 Mar 13 '14 at 18:52
  • You need to move the old file aside, or run `ln -fs` to force it. That will overwrite any existing log, though. – tripleee Mar 13 '14 at 19:15