The problem I'm trying to solve is illustrated by this example:
Let's say I want to write '/cgi-bin/counter.pl', a hit counter. It will access data file 'count.dat' also located in the cgi-bin dir. I want to increment the hit count by calling counter.pl from PHP (server-side) code in my home page (possibly sending GET or POST arguments to counter.pl), but I don't want the remote user to be able to call counter.pl and mess up the count.
That is, I want counter.pl to be callable from my Web site but not from anyone else's Web site.
Normally, of course, the user can browse to any CGI file. This will execute or interpret the file and send its output back to the user's browser. I would like this default behavior to continue for all CGI files except counter.pl.
I'm sure I'm missing something very basic indeed. It would be wonderful if someone can enlighten me, or point me to a good tutorial.
Thanks,
David
I'm using Apache/Unix. I'm using a "printenv" Perl in my cgi-bin dir. This cgi program shows the value of %ENV for each key.
I'm doing three tests with this printenv.pl:
1. Calling it directly as a browser URL.
2. Calling it from a page on the same site in javascript as "location.href = '...';".
3. Calling it from a page on the same site using the server-side preprocessing language PHP as "readfile(...);".
The result is that REQUEST_URI is always the same (/cgi-bin/printenv.pl).
David
#!/usr/local/bin/perlprint "Content-type: text/html\n\n";
if ($ENV{QUERY_STRING} eq "oktorun")
{execute code;}
else
{print "error message";}
exit(0);
Then just change your PHP call to
counter.pl?oktorun Anyone browsing your cgi-bin would then have to call the script with the correct query string or else it doesn't work.
unless ($ENV{'DOCUMENT_URI'}) {
print "Content-type: text/html\n\n";
print "Unauthorized Access!\n";
exit;
}
Does that cut it?
If you must have it be a CGI script, use .htaccess to deny requests from IP addresses other than your own. That way, only requests originating on your machine can hit it.
mdharrold: I like your idea of using an ordinary URI with the args set to a password. It is simple, I can change the password if I need to. Of course, it still requires a CGI program so the data files in cgi-bin can be accessed.
Key_Master: Your idea sounds interesting, but DOCUMENT_URI is not listed in the help file for Perl, nor does it appear in the output generated by printenv.pl. I don't see any useful variables in PHP, either (except for HTTP_REFERER, but it usually is not set at all).
amoore: Your solution, to put the data files in a dir protected by an .htaccess file, sounds like the best one to me, since it depends completely on the server and it protects the data itself, not programs or pages that use the data.
Now I have to figure out what to put in the .htaccess. I'll look in the Apache doc. The old trial and error method :).
And I'll have to choose between the password and the .htaccess method. It is not obvious to me which is better for general use.
Thanks, all, for your excellent help.
David
DOCUMENT_URI is a SSI environment variable and will not return anything if you call any script that uses it from the address bar (hence it's effectiveness). It only returns the virtual path/filename of the Web page the script was called from. Unlike REQUEST_URI or HTTP_REFERER it can't be spoofed. I can stickymail you an example if you like.
Overview here [ku.edu] of different CGI/SSI environmental variables.
Here are the details, in case anyone else whose server uses Apache is interested.
I put all my data files in a new directory (rather unimaginatively called "data") and added an .htaccess file (my server runs Apache/Unix, my development server runs Apache/Windows) with the following content:
<Files ~ ".*">
Order allow,deny
Allow from 127.0.0.1 <--- Replace with your IP
Satisfy All
</Files>
This tells the server to disallow any references to files in "data" except those that directly come from the server. That means that the files can only be accessed in server-side code (CGI files, ASP, PHP, etc.).
Thanks for your help.
David