| 1 | 95b003ff | Origo | #
 | 
      
        | 2 |  |  | # Config settings for mod_auth_tkt CGI scripts
 | 
      
        | 3 |  |  | # 
 | 
      
        | 4 |  |  | # Customise as required
 | 
      
        | 5 |  |  | #
 | 
      
        | 6 |  |  | 
 | 
      
        | 7 |  |  | package AuthTktConfig;
 | 
      
        | 8 |  |  | 
 | 
      
        | 9 |  |  | #use strict;
 | 
      
        | 10 |  |  | use Tie::DBI;
 | 
      
        | 11 |  |  | use Digest::MD5 qw(md5 md5_hex md5_base64);
 | 
      
        | 12 |  |  | use Digest::SHA qw(sha512_base64);
 | 
      
        | 13 |  |  | use Sys::Syslog qw( :DEFAULT setlogsock);
 | 
      
        | 14 |  |  | use Net::Subnet;
 | 
      
        | 15 |  |  | use ConfigReader::Simple;
 | 
      
        | 16 | 54401133 | hq | use Auth::GoogleAuth;
 | 
      
        | 17 | 4aef7ef6 | hq | use Geo::IP;
 | 
      
        | 18 | 95b003ff | Origo | 
 | 
      
        | 19 |  |  | # CSS stylesheet to use (optional)
 | 
      
        | 20 |  |  | our $STYLESHEET = 'tkt.css';
 | 
      
        | 21 |  |  | 
 | 
      
        | 22 |  |  | # Page title (optional)
 | 
      
        | 23 |  |  | our $TITLE = `cat /etc/stabile/config.cfg | sed -n -e 's/^ENGINENAME=//p'`;
 | 
      
        | 24 |  |  | chomp $TITLE;
 | 
      
        | 25 |  |  | $TITLE = $TITLE || 'Stabile';
 | 
      
        | 26 |  |  | $TITLE = "$TITLE - login";
 | 
      
        | 27 |  |  | 
 | 
      
        | 28 |  |  | # Fixed back location, overriding any set via back cookie or back arg
 | 
      
        | 29 |  |  | our $FIXED_BACK_LOCATION = '';
 | 
      
        | 30 |  |  | 
 | 
      
        | 31 |  |  | # Default back location, if none set via back cookie or back arg
 | 
      
        | 32 |  |  | our $DEFAULT_BACK_LOCATION = '/stabile/auth/login';
 | 
      
        | 33 |  |  | 
 | 
      
        | 34 |  |  | # Boolean flag, whether to fallback to HTTP_REFERER for back location
 | 
      
        | 35 |  |  | our $BACK_REFERER = 1;
 | 
      
        | 36 |  |  | 
 | 
      
        | 37 |  |  | # For autologin, mode to fallback to if autologin fails ('login' or 'guest')
 | 
      
        | 38 |  |  | our $AUTOLOGIN_FALLBACK_MODE = 'login';
 | 
      
        | 39 |  |  | 
 | 
      
        | 40 |  |  | # Additional cookies to clear on logout e.g. PHPSESSID
 | 
      
        | 41 |  |  | our @NUKE_COOKIES = qw(steamaccount tktuser);
 | 
      
        | 42 |  |  | 
 | 
      
        | 43 |  |  | # Debug flag
 | 
      
        | 44 |  |  | our $DEBUG = 0;
 | 
      
        | 45 |  |  | 
 | 
      
        | 46 |  |  | our $COOKIE_BASE = '';
 | 
      
        | 47 |  |  | $COOKIE_BASE = `cat /etc/stabile/cookiebase` if -e "/etc/stabile/cookiebase";
 | 
      
        | 48 |  |  | chomp $COOKIE_BASE;
 | 
      
        | 49 |  |  | $COOKIE_BASE = ".$COOKIE_BASE" unless ($COOKIE_BASE =~ /^\./);
 | 
      
        | 50 |  |  | 
 | 
      
        | 51 |  |  | 
 | 
      
        | 52 |  |  | # Username/password validation for login mode
 | 
      
        | 53 |  |  | #   (modify or point $validate_sub somewhere appropriate).
 | 
      
        | 54 |  |  | # The validation routine should return a true value (e.g. 1) if the 
 | 
      
        | 55 |  |  | #   given username/password combination is valid, and a false value
 | 
      
        | 56 |  |  | #   (e.g. 0) otherwise.
 | 
      
        | 57 |  |  | # This version uses Apache::Htpasswd and a standard htpasswd file.
 | 
      
        | 58 |  |  | sub validate
 | 
      
        | 59 |  |  | {
 | 
      
        | 60 | 54401133 | hq | 	my ($username, $password, $totp) = @_;
 | 
      
        | 61 | 95b003ff | Origo | 	require Apache::Htpasswd;
 | 
      
        | 62 |  |  | 	my $ht = Apache::Htpasswd->new({ passwdFile => '/etc/apache2/htpasswd-stabile', ReadOnly => 1 });
 | 
      
        | 63 |  |  | 	return $ht->htCheckPassword($username, $password);
 | 
      
        | 64 |  |  | }
 | 
      
        | 65 |  |  | 
 | 
      
        | 66 |  |  | sub sqlvalidate {
 | 
      
        | 67 | 54401133 | hq | 	my ($username, $password, $totp) = @_;
 | 
      
        | 68 | 95b003ff | Origo | 	$username = lc $username;
 | 
      
        | 69 |  |  | 	$username = $1 if ($username =~ /(.+)/); # Untaint
 | 
      
        | 70 |  |  |     my $config = ConfigReader::Simple->new("/etc/stabile/config.cfg",
 | 
      
        | 71 |  |  |         [qw(DBI_USER DBI_PASSWD)]);
 | 
      
        | 72 |  |  |     my $dbiuser =  $config->get('DBI_USER') || "irigo";
 | 
      
        | 73 |  |  |     my $dbipasswd = $config->get('DBI_PASSWD') || "";
 | 
      
        | 74 |  |  | 
 | 
      
        | 75 |  |  | 	my %register;
 | 
      
        | 76 |  |  | 	unless (tie %register,'Tie::DBI', {
 | 
      
        | 77 |  |  | 		db=>'mysql:steamregister',
 | 
      
        | 78 |  |  | 		table=>'users',
 | 
      
        | 79 |  |  | 		key=>'username',
 | 
      
        | 80 |  |  | 		autocommit=>0,
 | 
      
        | 81 |  |  | 		CLOBBER=>1,
 | 
      
        | 82 |  |  | 		user=>$dbiuser,
 | 
      
        | 83 |  |  | 		password=>$dbipasswd}) {return 0};
 | 
      
        | 84 |  |  | 
 | 
      
        | 85 |  |  | 	my $valid = 0;
 | 
      
        | 86 |  |  | 	my $validip = 0;
 | 
      
        | 87 |  |  | 	my $validuser = 0;
 | 
      
        | 88 |  |  | 
 | 
      
        | 89 | 54401133 | hq | 	my $u = $register{$username};
 | 
      
        | 90 |  |  | 	my $allowfrom = $u->{'allowfrom'};
 | 
      
        | 91 |  |  | 	my $totpsecret = $u->{'totpsecret'};
 | 
      
        | 92 | a2e0bc7e | hq | 	my $country;
 | 
      
        | 93 |  |  | 	my $continent;
 | 
      
        | 94 | 54401133 | hq | 
 | 
      
        | 95 | 95b003ff | Origo | 	my $from = $ENV{'REMOTE_ADDR'};
 | 
      
        | 96 |  |  | 	if ($allowfrom) {
 | 
      
        | 97 |  |  | 	    my @allows = split(/,\s*/, $allowfrom);
 | 
      
        | 98 |  |  | 	    foreach my $ip (@allows) {
 | 
      
        | 99 |  |  | 			if ($ip =~ /(\d+\.\d+\.\d+\.\d+\/\d+)/) { # Match a subnet definition
 | 
      
        | 100 |  |  | 				$validip = 1 if (subnet_matcher($1)->($from));
 | 
      
        | 101 | 04c16f26 | hq | 			} elsif ( $ip =~ /^\w\w$/ ) { # Match a country code
 | 
      
        | 102 | 4aef7ef6 | hq | 				my $geoip = Geo::IP->new(GEOIP_MEMORY_CACHE);
 | 
      
        | 103 |  |  | 				$country = $geoip->country_code_by_addr($from);
 | 
      
        | 104 |  |  | 				$validip = 1 if ($country eq $ip);
 | 
      
        | 105 | a2e0bc7e | hq | 				$continent = $geoip->continent_code_by_country_code($country);
 | 
      
        | 106 |  |  | 				$validip = 1 if ($continent eq $ip);
 | 
      
        | 107 | 95b003ff | Origo | 			} else {
 | 
      
        | 108 |  |  | 				$ip = $1 if ($ip =~ /(\d+\.)0\.0\.0/);
 | 
      
        | 109 |  |  | 				$ip = $1 if ($ip =~ /(\d+\.\d+\.)0\.0/);
 | 
      
        | 110 |  |  | 				$ip = $1 if ($ip =~ /(\d+\.\d+\.\d+\.)0/);
 | 
      
        | 111 |  |  | 				$validip = 1 if ($from =~ /^$ip/);
 | 
      
        | 112 |  |  | 			}
 | 
      
        | 113 |  |  | 	    }
 | 
      
        | 114 |  |  | 	} else {
 | 
      
        | 115 |  |  | 	    $validip = 1;
 | 
      
        | 116 |  |  | 	}
 | 
      
        | 117 |  |  | 	if ($register{$username}) {
 | 
      
        | 118 |  |  | 	    my $privileges = $register{$username}->{'privileges'};
 | 
      
        | 119 |  |  | 	    $validuser = 1 unless ($privileges =~ /d/);
 | 
      
        | 120 |  |  | 	}
 | 
      
        | 121 |  |  | 	if ($validip && $validuser) {
 | 
      
        | 122 |  |  |         # First check if md5 checksums match
 | 
      
        | 123 |  |  |         my $upassword = $register{$username}->{'password'};
 | 
      
        | 124 | 54401133 | hq |         if ($password && (
 | 
      
        | 125 |  |  | 			$upassword eq md5_base64($password)
 | 
      
        | 126 |  |  | 			|| $upassword eq sha512_base64($password)
 | 
      
        | 127 |  |  | 			|| ($totp && ($upassword eq $password)) # password is hashed when sent from totp form
 | 
      
        | 128 |  |  | 		)){
 | 
      
        | 129 |  |  | 			if ($totpsecret && $totpsecret ne '--') { # User has 2fa enabled
 | 
      
        | 130 |  |  | 				if ($totp) {
 | 
      
        | 131 |  |  | 					my $auth = Auth::GoogleAuth->new();
 | 
      
        | 132 |  |  | 					if ($auth->verify($totp, 1, $totpsecret)) {
 | 
      
        | 133 |  |  | 						$valid = 1;
 | 
      
        | 134 |  |  | 					} else {
 | 
      
        | 135 |  |  | 						$valid = 2;
 | 
      
        | 136 |  |  | 					}
 | 
      
        | 137 |  |  | 				} else {
 | 
      
        | 138 |  |  | 					$valid = 2;
 | 
      
        | 139 |  |  | 				}
 | 
      
        | 140 |  |  | 			} else {
 | 
      
        | 141 |  |  | 				$valid = 1;
 | 
      
        | 142 |  |  | 			}
 | 
      
        | 143 | 95b003ff | Origo |         # If plaintexts match, then assume we are dealing with a new user and convert the password to it's md5 checksum
 | 
      
        | 144 |  |  |         } elsif ($password && $register{$username}->{'password'} eq $password) {
 | 
      
        | 145 |  |  |             $valid = 1;
 | 
      
        | 146 |  |  |             eval {syslogit('info', "Adding system user $username: " . `/usr/sbin/useradd -m "irigo-$username"`); 1;};
 | 
      
        | 147 | 104449f5 | Origo | 			`echo "[User]\nSystemAccount=true" > /var/lib/AccountsService/users/irigo-$username`; # Don't show in login screen
 | 
      
        | 148 | 95b003ff | Origo |     #		eval {`/bin/echo irigo-$username:$password | /usr/sbin/chpasswd`; 1;}; # Doesn't work on Lucid, so we go through the hoops below...
 | 
      
        | 149 |  |  |             my $np = `/bin/echo irigo-$username:$password | /usr/sbin/chpasswd -S`; # -S option not supported on older versions
 | 
      
        | 150 |  |  |             $np =~ /irigo-$username:(.+)/;
 | 
      
        | 151 |  |  |             my $cpass = $1;
 | 
      
        | 152 |  |  |             eval {`/usr/sbin/usermod -p '$cpass' irigo-$username`; 1;};
 | 
      
        | 153 |  |  |             $register{$username}->{'password'} = sha512_base64($password);
 | 
      
        | 154 |  |  |     #        unless(-d "$basedir$username"){
 | 
      
        | 155 |  |  |     #            umask "0000";
 | 
      
        | 156 |  |  |     #            mkdir "$basedir$username" or syslogit("info", "Unable to create user dir for $username");
 | 
      
        | 157 |  |  |     #        }
 | 
      
        | 158 |  |  |         }
 | 
      
        | 159 |  |  | 		$register{$username}->{'lastlogin'} = $register{$username}->{'curlogin'};
 | 
      
        | 160 |  |  | 		$register{$username}->{'lastloginfrom'} = $register{$username}->{'curloginfrom'};
 | 
      
        | 161 |  |  | 		$register{$username}->{'curlogin'} = time;
 | 
      
        | 162 |  |  | 		$register{$username}->{'curloginfrom'} = $ENV{'REMOTE_ADDR'};
 | 
      
        | 163 |  |  | 	}
 | 
      
        | 164 |  |  | 	return $valid;
 | 
      
        | 165 |  |  | 	untie %register;
 | 
      
        | 166 |  |  | }
 | 
      
        | 167 |  |  | 
 | 
      
        | 168 |  |  | 
 | 
      
        | 169 |  |  | #our $validate_sub = \&validate;
 | 
      
        | 170 |  |  | our $validate_sub = \&sqlvalidate;
 | 
      
        | 171 |  |  | 
 | 
      
        | 172 |  |  | # For guest mode (if used), setup guest username
 | 
      
        | 173 |  |  | #   Could use a counter or a random suffix etc.
 | 
      
        | 174 |  |  | sub guest_user { return 'guest' }
 | 
      
        | 175 |  |  | our $guest_sub = \&guest_user;
 | 
      
        | 176 |  |  | 
 | 
      
        | 177 |  |  | 1;
 | 
      
        | 178 |  |  | 
 | 
      
        | 179 |  |  | sub syslogit {
 | 
      
        | 180 |  |  | 	my ($priority, $msg) = @_;
 | 
      
        | 181 |  |  | 
 | 
      
        | 182 |  |  | 	setlogsock('unix');
 | 
      
        | 183 |  |  | 	# $programname is assumed to be a global.  Also log the PID
 | 
      
        | 184 |  |  | 	# and to CONSole if there's a problem.  Use facility 'user'.
 | 
      
        | 185 |  |  | 	openlog("", 'pid,cons', 'user');
 | 
      
        | 186 |  |  | 	syslog($priority, $msg);
 | 
      
        | 187 |  |  | 	closelog();
 | 
      
        | 188 |  |  | 	return 1;
 | 
      
        | 189 |  |  | }
 |