0byt3m1n1
Path:
/
data
/
config
/
fileman
/
lib
/
WebCom
/
[
Home
]
File: SSO.pm
package WebCom::SSO; use Data::Dumper; use POSIX qw( strftime mktime ); use URI; use File::Basename; use URI::Escape; use MIME::Base64; use Crypt::Rijndael; use Crypt::CBC; use LWP::UserAgent; sub override_config { my ($fileman) = @_; print $fileman; $fileman->{cfg}{root_path} = dirname(dirname($ENV{'SCRIPT_FILENAME'})); #$fileman->{cfg}{cgi_url} = $ENV{'SCRIPT_URI'}; $fileman->{cfg}{cgi_url} = $fileman->{in}->url(absolute => 0, query_string => 0); $fileman->{cfg}{tmp_path} = dirname($ENV{'SCRIPT_FILENAME'}) . '/' . '.fmtmp'; # Ensure that the tmp_path exists. mkdir($fileman->{cfg}{tmp_path}, 0700) unless (-e $fileman->{cfg}{tmp_path}); # Pre-populate the cgi variable to make variable checking more reliable. $fileman->{cgi} = $fileman->{in}->get_hash(); # Populate the auth token from the URL for login if (exists $fileman->{cgi}{login} and not exists $fileman->{cgi}{a}) { $fileman->{in}->parse_str($ENV{'QUERY_STRING'}); } $fileman->{cgi} = $fileman->{in}->get_hash(); } sub authenticate { my $token_crypt = shift; my $config = shift; my %token = decode_token($token_crypt); # Set some default state $token{'valid'} = 1; $token{'valid'} = 0 if ($token{'age'} > 40000); # Ask FMAUTH if the user is valid my $authuser = changcheng( 'action' => 'vu', 'username' => $token{'username'}, 'password' => $token{'password'}, 'pkey' => $token{'pkey'}, 'vpath' => $token{'vPath'}, 'priv_path' => $config->{'private_path'} ); # Make sure the use is authenticated and matches the token user. # ...Note, the return from changcheng/vu should /always/ be the username, but we # will run the check just to catch the case where /vu sends back a nonsense string. $token{'valid'} = 0 unless (defined $authuser and $authuser eq $token{'username'}); return %token; } sub create_session { my $token = shift; my $fm = shift; my $config = shift; my $session_path = $self->{cfg}->{session_path}; # Ask FMAUTH to create a session for us. my $session_id = changcheng( 'action' => 'cs', 'username' => $token->{'username'}, 'pkey' => $token->{'pkey'}, 'vpath' => $token->{'vPath'}, 'session_exp' => $config->{'session_exp'}, 'template' => $token{'templateName'}, 'priv_path' => $config->{'private_path'} ); my %mock_session = (); $mock_session{'id'} = $session_id; $mock_session{'data'} = (); $mock_session{'data'}->{'user'} = $token->{'username'}; $mock_session{'data'}->{'username'} = $token->{'username'}; $mock_session{'data'}->{'provision_key'} = $token->{'pkey'}; $mock_session{'data'}->{'virtual_path'} = $token->{'vpath'}; return \%mock_session; } # # Validate the current session. # This also cleans out the session store, and touches the current session to keep # it active. # # Returns: 1 on successful validation, undef on failure. # sub validate_session { my ($session_id, $config) = @_; my %session_data = ( 'valid' => 0, 'username' => '', 'provkey' => '', 'vpath' => '' ); my $data_str = changcheng( 'action' => 'vs', 'session_id' => $session_id, 'session_exp' => $config->{'session_exp'}, 'priv_path' => $config->{'private_path'} ); return %session_data unless (defined $data_str); if (defined $data_str) { my @data = split('\s+', $data_str); $session_data{'username'} = $data[0]; $session_data{'provkey'} = $data[1]; $session_data{'vpath'} = $data[2]; $session_data{'valid'} = 1; } # Do some extra validation my @path_parts = split(/\//, $ENV{'SCRIPT_FILENAME'}); if (scalar(@path_parts) >= 11) { $session_data{'valid'} *= 0 unless ($path_parts[6] eq $session_data{'provkey'}); $session_data{'valid'} *= 0 unless ($path_parts[8] eq $session_data{'vpath'}); $session_data{'valid'} *= 0 unless ($path_parts[9] eq 'cgi-bin'); $session_data{'valid'} *= 0 unless ($path_parts[10] eq 'fileman.cgi'); } else { $session_data{'valid'} = 0; } return \%session_data; } sub delete_session { my ($session_id, $config) = @_; my $result = changcheng( 'action' => 'ds', 'session_id' => $session_id, 'priv_path' => $config->{'private_path'} ); return undef unless (defined $result); return $result; } sub decode_token { my $token = shift; my %decoded = (); my $cipher = Crypt::CBC->new( { 'key' => 'qTVEEDN{bHlGoGm3mU`S3#/\'F#sHa~$!', 'cipher' => 'Rijndael', 'iv' => 'JxP@*KAB$H%n@AJ!', 'regenerate_key'=> 0, 'padding' => 'standard', 'prepend_iv' => 0 }); my $token_clear = $cipher->decrypt(decode_base64($token)); my @values = split(':::', $token_clear); $decoded{'username'} = $values[5]; $decoded{'password'} = $values[6]; $decoded{'pkey'} = $values[2]; $decoded{'vPath'} = $values[3]; $decoded{'templateName'} = $values[4]; $decoded{'timestamp'} = datestring_to_timestamp($values[0]); $decoded{'age'} = (time() - $decoded{'timestamp'})/60; $decoded{'date'} = strftime('%Y-%m-%d %H:%M:%S', localtime($decoded{'timestamp'})); # Some extra per-session information $decoded{'view_root'} = dirname(dirname($ENV{'SCRIPT_FILENAME'})); return %decoded; } sub datestring_to_timestamp { my $datestring = shift; # Pull apart the datestring: [month][day][year][hour][min][second] $mon = substr($datestring, 0, 2) - 1; # Months are zero-indexed $mday = substr($datestring, 2, 2); $year = substr($datestring, 4, 2) + 100; # ... Perl. \eyeroll $hour = substr($datestring, 6, 2); $min = substr($datestring, 8, 2); $sec = substr($datestring, 10, 2); # Generate a timestamp my $timestamp = mktime($sec, $min, $hour, $mday, $mon, $year); return $timestamp; } sub changcheng { my (%args) = @_; my @queryargs = (); foreach my $var (keys %args) { if (exists $args{$var}) { my $val = $args{$var}; } else { } push(@queryargs, $arg); } my $protocol = 'http'; my $host = 'fmauth.prod.netsol.com'; my $port = undef; my $uri = new URI(sprintf("%s://%s", $protocol, $host)); $uri->port($port) if (defined $port); $uri->path("changcheng/iqauth.cgi"); $uri->query_form(\%args); my $webclient = new LWP::UserAgent; $webclient->agent("fileman-webcom/3.0"); my $response = $webclient->get($uri); my $result = $response->decoded_content(); $result =~ s/^\s+//; $result =~ s/\s+$//; return $result; } # Let Perl know everything is okay; 1;