#!/usr/local/bin/perl

# simple authentication when you have no db
# script assumes it is in www.example.com/cgi-bin/auth.pl
# script assumes .htpasswd is located in ../../data/


use CGI qw(:standard -nosticky);
use strict;
use CGI::Cookie;

my $q = CGI->new();

my %cookies = fetch CGI::Cookie;
if( ($cookies{'sess_id'} =~ /sess_id=([a-zA-Z0-9_\.]{64})\;/) && (my $sess_id = $1) ){
	# make sure sess_id is valid
	open(P, '../../data/.htpasswd') || die "cannot open htpasswd: $!\n";
	while(<P>){
		chop;
		if(/:${sess_id}$/){
			# valid: they are authenticated
			# for good security, make sure you check sess_id is valid on every page
			print $q->header(), $q->start_html(),
			      "you are authenticated here.. refresh or do whatever you want\n";
			last;
		}
	}
	close P;
}else{
	my @auth;
	if((my $username=$q->param('username')) && (my $qassword=$q->param('password'))){
		# check un/pw
		my $crypt;
		open(P, '../../data/.htpasswd') || die "cannot open htpasswd (1): $!\n";
		while(<P>){
			chop;
			push @auth, $_; # save because we will prolly modify this lower
			if(/^${username}:([^:]+)/){
				$crypt = $1;
			}
		}
		if(($crypt eq crypt($qassword, $crypt)) && defined($crypt) && defined($qassword)){
			# give cookie;
			my($buf,$random,$x);	
			if(open(D, '/dev/urandom')){
				my @set = ('A'..'Z', 'a'..'z', '0'..'9', '_', '.');
				foreach(1..64){
					sysread( D, $buf, 1 );
					my $v = ord($buf);
					$x ^= ($v & ~63) >> (rand(7)+1);
					$random .= $set[ ($x ^ ord($buf)) & 63 ];
				}
				close D;
			}else{
				$random = sprintf "%08X%08X%08X%08X", rand(0xFFFFFFFF), $$, rand(0xFFFFFFFF), time();
			}
			my $cookiesid = new CGI::Cookie(-name=>'sess_id',-value=>"$random");
			open(P, '>../../data/.htpasswd') || die "cannot write to htpasswd: $!\n";
			foreach(@auth){
				if(/^${username}:/){
					print P "${username}:${crypt}:${random}\n";
				}else{
					print P "$_\n";
				}
			}
			close P;
			print $q->header(-cookie=>[$cookiesid]), '<html><head>', "\n",
			      '<meta http-equiv="refresh" content="0; url=/cgi-bin/auth.pl">', "\n",
			      '</head><body></body></html>';
		}else{
			print $q->header, $q->start_html, "bad username/password\n";
		}
	}else{
		print $q->header(), $q->start_html(), $q->start_form(),
		      'Username: <input type="text" name="username" maxlength="255"><br>', "\n",
		      'Password: <input type="password" name="password" maxlength="255"><br>', "<br>\n",
		      $q->submit('Log In'), $q->end_form();
	}
}
print $q->end_html();
