stockton
Posts: 136
Joined: Mon Aug 24, 2015 6:06 am
Location: South Africa
Contact: Website

Understanding permissions

Sat Aug 18, 2018 2:41 pm

I am attempting to create a "real time" web page under Apache2 using HTML and AJAX and a C program that I wrote.
The web page includes a call to Ajax which in turn calls my C program.
Each of these parts works perfectly well when used apart from each other but in combination I get a permissions error from my C program when attempting to read the file containing the required data.
As I said it all works fine till my C program attempts to open the file.
If I run the C program from the command line it works fine.
I therefore do not believe that I have a program problem but rather a permission problem when running with Apache2.
Obviously the HTML & Javascript & C executable are in /var/www/html/lcars but the file to be read is on a USB connect HDD, namely /media/pi/MyPassport/Axpert/
I have also ended up at times having the javascript displaying/returning the C program rather than the contents of the file that the C program should have read.
Please tell me where I start resolving this.

User avatar
thagrol
Posts: 3310
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: Understanding permissions

Sat Aug 18, 2018 6:42 pm

Start by posting the error message(s) you're getting.

To view current permissions

Code: Select all

ls -al  /media/pi/MyPassport/Axpert/*
or whatever path your file is on.

My guess is that the file you're having trouble with isn't world readable and/or world writeable (depands on whether your trying to open it ro or rw). Or both.

It's also possible that the C program isn't world executable so check permissions there too.

Without the error mesasge(s) I can't say which.

In either case the quick but dirty and insecure fix is to add the relevant permissions for all users. You'll need to do this either as the owner of the file or with sudo/as root. An example:

Code: Select all

chmod a+rwx /path/to/file
which grants read, write and execute permissions to everyone.

A better fix would be to change ownership of the file(s) to the user running apache and grant permission only to that user. Or add a new groups, add the file owner and the apache user to that group then grant the required permissions to that group.

A quick google for "linux file permissions" and a reading of the man page for chmod would probably be of use to you.
Arguing with strangers on the internet since 1993.

fbe
Posts: 645
Joined: Thu Aug 17, 2017 9:08 pm

Re: Understanding permissions

Sat Aug 18, 2018 11:24 pm

Start with looking into /var/log/apache2/error.log
You should be aware, that all processes, started from apache2, are running with the privileges of user www-data.

stockton
Posts: 136
Joined: Mon Aug 24, 2015 6:06 am
Location: South Africa
Contact: Website

Re: Understanding permissions

Sun Aug 19, 2018 5:02 am

I got a step further but now the command
xhr.open('GET', './LastLine', true);
Returns the content of my C binary rather than return the result of running the binary.

/var/www/html/lcars $ ls -al ./LastLine
-rwxr-xr-x 1 root root 8376 Aug 17 12:21 LastLine

fbe
Posts: 645
Joined: Thu Aug 17, 2017 9:08 pm

Re: Understanding permissions

Sun Aug 19, 2018 7:14 am

Move your LastLine binary to /usr/lib/cgi-bin, then try:

Code: Select all

curl http://localhost/cgi-bin/LastLine
in a terminal window (or ssh session) on your RPi.
If it returns something like:

Code: Select all

pi@raspberrypi:~ $ curl http://localhost/cgi-bin/LastLine
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /cgi-bin/LastLine was not found on this server.</p>
<hr>
<address>Apache/2.4.25 (Raspbian) Server at localhost Port 80</address>
</body></html>
you need to enable cgi.

Code: Select all

sudo a2enmod cgi
sudo systemctl restart apache2
If things improve, you may try to figure out, how to enable cgi execution in directory /var/www/html/lcars or leave your binaries in /usr/lib/cgi-bin (or a subdirectory) and use

Code: Select all

xhr.open('GET', '/cgi-bin/LastLine', true);

stockton
Posts: 136
Joined: Mon Aug 24, 2015 6:06 am
Location: South Africa
Contact: Website

Re: Understanding permissions

Sun Aug 19, 2018 8:40 am

Thank you FBE. I followed all your steps but still I get the contants of the binary displayed rather than the result of running the binary.
pi@RPiDev:/var/www/html/lcars $ ls -al /usr/lib/cgi-bin/LastLine
-rwxr-xr-x 1 root root 8376 Aug 19 10:32 /usr/lib/cgi-bin/LastLine
pi@RPiDev:/var/www/html/lcars $ ls -al cgi-bin/LastLine
-rwxr-xr-x 1 root root 8376 Aug 19 10:32 cgi-bin/LastLine

I diid not alter the javascript call to LastLine but now that I made it /cgi-bin/LastLine I get a 500 error.

fbe
Posts: 645
Joined: Thu Aug 17, 2017 9:08 pm

Re: Understanding permissions

Sun Aug 19, 2018 10:37 am

Did you look into /var/log/apache2/error.log?

stockton
Posts: 136
Joined: Mon Aug 24, 2015 6:06 am
Location: South Africa
Contact: Website

Re: Understanding permissions

Sun Aug 19, 2018 11:24 am

I am getting
[Sun Aug 19 13:15:31.672730 2018] [cgi:error] [pid 5771] [client 192.168.0.176:54656] End of script output before headers: LastLine, referer: http://192.168.0.120/lcars/solar5.html
in /var/log/apache2/error.log

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h> 

int main(int argc , char *argv[])
    {
    FILE *fd;                           // File pointer
    char filename[] = "solar.log";       // file to read
    long max_len = 110 + 1;             // define the max length of the line to read
    char buff[max_len + 1];             // define the buffer and allocate the length

    if ((fd = fopen(filename, "rb")) != NULL)    
        {
        fseek(fd, -max_len, SEEK_END);            // set pointer to the end of file minus the length you need. 
                                                  //     Presumably there can be more than one new line caracter
        fread(buff, max_len-1, 1, fd);            // read the contents of the file starting from where fseek() positioned us
        fclose(fd);                               // close the file
        }
    else
        printf("%s %d FileOpen error\n",__FILE__, __LINE__);
    buff[max_len-1] = '\0';                   // close the string
    char *last_newline = strrchr(buff, 'S'); // find last occurrence of newlinw 
    char *last_line = last_newline+1;         // jump to it
    printf("Content-type: text/html\n");
    printf("%s\n", last_line);
    }

fbe
Posts: 645
Joined: Thu Aug 17, 2017 9:08 pm

Re: Understanding permissions

Sun Aug 19, 2018 12:51 pm

There must be one empty line after the header lines.
You must not output anything to stdout before you finished the header lines.

For simplicity:

Code: Select all

...
    printf("Content-type: text/html\n");
    printf("\n");

    if ((fd = fopen(filename, "rb")) != NULL)    
...
    buff[max_len-1] = '\0';                   // close the string
    char *last_newline = strrchr(buff, 'S'); // find last occurrence of newlinw 
    char *last_line = last_newline+1;         // jump to it
    printf("%s\n", last_line);
The file solar.log must be in the same directory like LastLine. You could put it into any other directory, if you use an absolute path, e.g.

Code: Select all

char filename[] = "/home/pi/Documents/SolarProject/solar.log";
(actually files of this kind often reside below /var/lib/...).
www-data needs only read permission for solar.log in this examlpe. So www-data should not be the owner of this file and permissions should be set to 644.
Make sure, that solar.log contains at least one "S".

stockton
Posts: 136
Joined: Mon Aug 24, 2015 6:06 am
Location: South Africa
Contact: Website

Re: Understanding permissions

Sun Aug 19, 2018 1:25 pm

I made the change to the source that you suggested but I still get a 500 and /var/log/apache2/error.log still contains
[Sun Aug 19 15:16:07.268215 2018] [cgi:error] [pid 5771] [client 192.168.0.176:55366] End of script output before headers: LastLine, referer: http://192.168.0.120/lcars/solar5.html

I have attempted altering the files permissions to 644 but it persists in being 777.
I do not understand the S you mentioned.

fbe
Posts: 645
Joined: Thu Aug 17, 2017 9:08 pm

Re: Understanding permissions

Sun Aug 19, 2018 2:05 pm

nano LastLine.c

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

int main(int argc , char *argv[])
    {
    FILE *fd;                           // File pointer
    char filename[] = "solar.log";       // file to read
    long max_len = 110 + 1;             // define the max length of the line to read
    char buff[max_len + 1];             // define the buffer and allocate the length
    printf("Content-type: text/html\n");
    printf("\n");

    if ((fd = fopen(filename, "rb")) != NULL)
        {
        fseek(fd, -max_len, SEEK_END);            // set pointer to the end of file minus the length you need.
                                                  //     Presumably there can be more than one new line caracter
        fread(buff, max_len-1, 1, fd);            // read the contents of the file starting from where fseek() positioned us
        fclose(fd);                               // close the file
        }
    else
        printf("%s %d FileOpen error\n",__FILE__, __LINE__);
    buff[max_len-1] = '\0';                   // close the string
    char *last_newline = strrchr(buff, 'S'); // find last occurrence of newlinw
    char *last_line = last_newline+1;         // jump to it
    printf("%s\n", last_line);
    }
Ctrl+o, Ctrl+x

Code: Select all

gcc LastLine.c -o LastLine
sudo install -m755 -o root -g root LastLine /usr/lib/cgi-bin/LastLine
echo 'TEST' > solar.log
echo 'Hello' >> solar.log
echo 'World' >> solar.log
sudo install -m644 -o root -g root solar.log /usr/lib/cgi-bin/solar.log

Code: Select all

pi@raspberrypi:~ $ curl http://localhost/cgi-bin/LastLine
T
Hello
World

stockton
Posts: 136
Joined: Mon Aug 24, 2015 6:06 am
Location: South Africa
Contact: Website

Re: Understanding permissions

Sun Aug 19, 2018 5:27 pm

Thanks you suggestions worked for me. You should be able to browse to it at 196.32.102.29/lcars/solar5.html.
I placed a copy of solar.log into the cgi-bin folder as you suggested but I would prefer to use the actual file at /media/pi/MyPassport/Axpert
The traffic on solar.log is heavy and as I don't want this on my sd card I have placed it on a USB connected HDD.
Can this be done?

fbe
Posts: 645
Joined: Thu Aug 17, 2017 9:08 pm

Re: Understanding permissions

Sun Aug 19, 2018 6:23 pm

This could be done, but I would not recommend using a drive for a webserver, that is only mounted when you login to the desktop. /media/pi/MyPassport appears to be mounted this way. It will be unavailable, if you, for some reason, select "Boot into CLI" or disable the "Automatically login as user 'pi'" option in your Raspberry Pi Configuration.

If you want to use /media/pi/MyPassport anyway, make sure that www-data has permission to read and search (execute) /media/pi

Code: Select all

sudo su www-data -s /bin/sh -c "ls -la /media/pi"

stockton
Posts: 136
Joined: Mon Aug 24, 2015 6:06 am
Location: South Africa
Contact: Website

Re: Understanding permissions

Mon Aug 20, 2018 4:57 am

Unfortunately that did not work.
pi@RPiDev:~ $ sudo su www-data -s /bin/sh -c "ls -la /media/pi"
ls: cannot open directory '/media/pi': Permission denied
pi@RPiDev:~ $ ls -al /media/pi/
total 264
drwxr-x---+ 4 root root 4096 Aug 18 05:46 .
drwxr-xr-x 3 root root 4096 Mar 8 14:26 ..
drwxrwxrwx 1 pi pi 131072 Jan 1 1970 MyPassport
drwxrwxrwx 1 pi pi 131072 Jan 1 1970 My Passport
BTW As this is really an exercise for me I am not too concerned about the USB occasionally being unavailable.

Return to “Raspberry Pi OS”