LAM Alaska - About an authenticated user

Making a CGI script recognize if being accessed by an authenticated user.

About this page

This web page shows by example how to make a CGI script recognize if being accessed by an authenticated user and act differently if so. The example shows a recent change to the man perl cgi script on this site. The change was made so that some man pages would not be available to the public.

Overview of the change

Although the change was implemented so that a single version of the man.cgi-pl perl script handles both behaviors, a symbolic link was created in the Private/Scripts folder pointing to the Public/Scripts version so that the Apache server treats it as if it were two versions.

ln -sT /var/www/html/Public/Scripts/man.cgi-pl /var/www/html/Private/Scripts/man.cgi-pl
This is because the existence of the REMOTE_USER environment variable is used which is only set by Apache for pages in a directory or subdirectory that requires authentication. The symbolic link allows there to be only one program (only one place to edit and maintain) but have Apache control access to to what it treats as a separate program. This then allows the program to test for the the existence of the REMOTE_USER environment variable to control which set of man pages are made available.

Perl cgi script code segment

if (not defined $ENV{'REMOTE_USER'}) {     # If not an authenticated remote user
    $ENV{'MANPATH'} = '/usr/share/man';    # Set MANPATH to omit local man pages.
}
The end effect of this change only affects the display of man pages by the Appache server to unauthenticated users on the unsecured side of the website. A user who signs on to the secure side of the website is unaffected. A user who goes to the secure side and uses the man link without authorizing will get an "Authorization Required!" message.

If unauthenticated, a user can only see man pages in the /usr/share/man tree.

Apache configuration

The change described above is dependant on an Apache configuration detailed below.

Apache configuration description

In the main Apache configuration file an Alias is set for /Public and cgi-scripts are enabled in that directory. A number of locations including /Private are forced to be handled by the secure side of the server (port 443).

In the default host configuraton file a document root is set but scripts are allowed as if they were in the root directory with file names without an extension by a conditional rewrite rule. An aditional rewrite rule allows the man pages to be accesses as if they were files in a man directory.

In the ssl virtual host configuraton file a different document root is set, scripts are allowed anywhere within that directory tree and Apache is instructed to follow symbolic links. Again some scripts are allowed to be accessed as if they were in the root directory with file names without an extension by a conditional rewrite rule. This rule is applied to scripts in the /Private directory rather than the /Public directory and the Last flag is used so that no other rules are checked when this rule is satisfied. The order of the rules and the Last flag make it so that if a script exists in both the /Public and /Private folders the /Private script will be used if accessed from the secured side of the site. A number of locations including /Private can only be accessed by authenticated users. These locations were previously forced to be handled on the secure port which means the authentication process only occurs on the secure port.

Apache configuration directives:

In file: /etc/httpd/conf/httpd.conf
...
Alias /Public /var/www/html/Public
<Directory "/var/www/html/Public">
   Options +ExecCGI
   AddHandler cgi-script .cgi-pl
</Directory>
...
<LocationMatch "^/(Log/On|Private|usage|ts|Bk|server-|phpMyAdmin|Squid|ErrorLogs|Install|cgi-bin)">
   RewriteEngine on
   RewriteCond %{SERVER_PORT} !^443$
   RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</LocationMatch>
...
In file: /etc/httpd/conf/vhosts.d/00_default_vhosts.conf
...
DocumentRoot "/var/www/no-ssl"
...
RewriteCond %{REQUEST_FILENAME} (.*)$
   RewriteCond /var/www/html/Public/Scripts%1.cgi-pl -f
   RewriteRule (.+)$ /Public/Scripts%1.cgi-pl [PT]
RewriteRule ^/man/(.+)$ /Public/Scripts/man.cgi-pl?Submit=View&Keyword=$1 [PT]
...
In file: /etc/httpd/conf/vhosts.d/01_default_ssl_vhost.conf
...
DocumentRoot "/var/www/html"
<Directory "/var/www/html">
   Options +ExecCGI FollowSymLinks
   AddHandler cgi-script .cgi-pl
</Directory>
...
RewriteRule ^/man/(.+)$ /Private/Scripts/man.cgi-pl?Submit=View&Keyword=$1
...
RewriteCond %{REQUEST_FILENAME} (.*)$
RewriteCond %{DOCUMENT_ROOT}/Private/Scripts%1.cgi-pl -f
RewriteRule (.+)$ /Private/Scripts%1.cgi-pl [L]
...
<LocationMatch "^/(Log/On|Private|usage|ts|Bk|Zz|server-.*|phpMyAdmin|Squid|ErrorLogs.*|Install|cgi-bin)">
   SSLRequireSSL 
   AuthType Basic
   AuthName "Authenticated Users"
   AuthUserFile /var/www/.htpasswd
   AuthGroupFile /var/www/.htgroup
   require group lam
</LocationMatch>
<Directory "/var/www/html/Private">
   SSLRequireSSL 
   AuthType Basic
   AuthName "Authenticated Users"
   AuthUserFile /var/www/.htpasswd
   AuthGroupFile /var/www/.htgroup
   require group lam
</Directory>
...

Summary

This page shows a small code segment and a relatively simple change but it is dependant on the web server to set an environment variable under specific circumstances that can then be tested by the program. All the Apache configuration detailed above was already in place but a minor change was made to one rule. That was to replace /Public with /Private in the rewrite rule for "^/man/(.+)$" in the secure configuration file.

Please contact me if you have comments about this page.


1,146 visits (1 today, 2 this week, 12 this month, 101 this year)
Uptime: 12:53:07 up 11:29, 0 users, load average: 0.00, 0.01, 0.04
54.162.108.167 GET from server z.lam1.us

Monday, June 26, 2017 @ 12:53:07 PM
z.ServerAdmin@lam1.us