* Making good progress on the internal login/account methods. The user can now log in, though the first reload logs them right back out. Lots still broken.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 7 years ago
parent 66928edb06
commit 3fce021498
  1. 9
      Anvil/Tools.pm
  2. 544
      Anvil/Tools/Account.pm
  3. 36
      Anvil/Tools/Database.pm
  4. 5
      Anvil/Tools/Get.pm
  5. 6
      Anvil/Tools/Remote.pm
  6. 20
      Anvil/Tools/Storage.pm
  7. 6
      Anvil/Tools/System.pm
  8. 65
      cgi-bin/home
  9. 17
      html/skins/alteeve/main.css
  10. 32
      html/skins/alteeve/main.html
  11. 19
      share/words.xml
  12. 2
      tools/anvil-change-password
  13. 4
      tools/anvil.sql

@ -215,7 +215,7 @@ sub new
### TODO: Calls to allow the user to override defaults...
# Local parameters...
}
elsif($parameter)
elsif ($parameter)
{
# Um...
print $THIS_FILE." ".__LINE__."; Anvil::Tools->new() invoked with an invalid parameter. Expected a hash reference, but got: [$parameter]\n";
@ -733,7 +733,12 @@ sub _set_defaults
stty => "",
},
use_base2 => 1,
user => "admin",
user => {
name => "admin",
cookie_valid => 0,
language => "en_CA",
skin => "alteeve",
},
};
$anvil->data->{defaults} = {
## Network stuff... The second octet auto-increments to handle N-number of netowrks. As such,

@ -13,8 +13,13 @@ my $THIS_FILE = "Account.pm";
### Methods;
# encrypt_password
# login
# logout
# read_cookies
# read_details
# validate_password
# _build_cookie_hash
# _write_cookies
=pod
@ -90,10 +95,24 @@ If anything goes wrong, all four keys will have empty strings.
Parameters
=head3 algorithm (optional)
If set, the password will be encrypted using the given algoritm. Otherwise, c<< sys::password::algorithm >> is used. If that is not set, C<< sha256 >> is used.
=head3 hash_count (Optional, default 500000)
This controls how many times we re-encrypt the password hash. This is designed to slow down how quickly a brute-force attacker can test hashes. This should be a high enough number to take some time (~0.5 seconds) on a modern machine, but not so high that it noticeably slows down user login attempts.
If set to C<< 0 >>, no re-hashing will occur, but the initial hash still will.
=head3 password (required)
This is the password (string) to encrypt.
=head3 salt (optional)
This is the salt to use when hashing the password. If this is not passed, a new salt will be generated.
=cut
sub encrypt_password
{
@ -102,11 +121,15 @@ sub encrypt_password
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $user_password_hash = defined $parameter->{password} ? $parameter->{password} : "";
my $user_hash_count = $anvil->data->{sys}{password}{hash_count} =~ /^\d+$/ ? $anvil->data->{sys}{password}{hash_count} : 500000;
my $user_algorithm = $anvil->data->{sys}{password}{algorithm} ? $anvil->data->{sys}{password}{algorithm} : "sha512";
my $algorithm = defined $parameter->{algorithm} ? $parameter->{algorithm} : "";
my $hash_count = defined $parameter->{hash_count} ? $parameter->{hash_count} : "";
my $password = defined $parameter->{password} ? $parameter->{password} : "";
my $salt = defined $parameter->{salt} ? $parameter->{salt} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
password => $anvil->Log->secure ? $user_password_hash : "--",
algorithm => $algorithm,
hash_count => $hash_count,
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
salt => $salt,
}});
# We'll fill these out below if we succeed.
@ -118,18 +141,37 @@ sub encrypt_password
};
# Make sure we got a string
if (not $user_password_hash)
if (not $password)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Account->encrypt_password()", parameter => "password" }});
return($answer);
}
my $user_password_hash = $password;
# Set the re-hash count, if not already set.
my $user_hash_count = $hash_count;
if ($user_hash_count eq "")
{
$user_hash_count = $anvil->data->{sys}{password}{hash_count} =~ /^\d+$/ ? $anvil->data->{sys}{password}{hash_count} : 500000;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_hash_count => $user_hash_count }});
}
# Generate a salt.
my $user_salt = $anvil->Get->_salt;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_salt => $user_salt }});
my $user_salt = $salt;
if (not $user_salt)
{
$user_salt = $anvil->Get->_salt;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_salt => $user_salt }});
}
### TODO: Look at using/support bcrypt as the default algorithm. Needed RPMs are already in the el7 AN!Repo.
# We support sha256, sha384 and sha512, possible new ones later.
my $user_algorithm = $algorithm;
if (not $algorithm)
{
$user_algorithm = $anvil->data->{sys}{password}{algorithm} ? $anvil->data->{sys}{password}{algorithm} : "sha512";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_algorithm => $user_algorithm }});
if ($user_algorithm eq "sha256" )
{
$user_password_hash = sha256_base64($user_password_hash.$user_salt);
@ -193,21 +235,307 @@ sub encrypt_password
'answer->user_salt' => $answer->{user_salt},
'answer->user_hash_count' => $answer->{user_hash_count},
'answer->user_algorithm' => $answer->{user_algorithm},
}});
return($answer);
}
=head2 login
This checks to see if the CGI C<< username >> and C<< password >> passed in are for a valid user or not. If so, their details are loaded and C<< 0 >> is returned. If not, C<< 1 >> is returned.
This method takes no parameters.
=cut
sub login
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
if ((not $anvil->data->{cgi}{username}{value}) or (not $anvil->data->{cgi}{password}{value}))
{
# The user forgot something...
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0027"}) }});
return(1);
}
my $query = "
SELECT
user_uuid,
user_password_hash,
user_salt,
user_algorithm,
user_hash_count
FROM
users
WHERE
user_algorithm != 'DELETED'
AND
user_name = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->data->{cgi}{username}{value})."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if (not $count)
{
# User not found.
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0027"}) }});
return(1);
}
my $user_uuid = $results->[0]->[0];
my $user_password_hash = $results->[0]->[1];
my $user_salt = $results->[0]->[2];
my $user_algorithm = $results->[0]->[3];
my $user_hash_count = $results->[0]->[4];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
user_uuid => $user_uuid,
user_password_hash => $user_password_hash,
user_salt => $user_salt,
user_algorithm => $user_algorithm,
user_hash_count => $user_hash_count,
}});
# Test the passed-in password.
my $test_password_answer = $anvil->Account->encrypt_password({
password => $anvil->data->{cgi}{password}{value},
salt => $user_salt,
algorithm => $user_algorithm,
hash_count => $user_hash_count,
});
my $test_password_hash = $test_password_answer->{user_password_hash};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { test_password_hash => $test_password_hash }});
if ($test_password_hash eq $user_password_hash)
{
# User passed a valid username/password. Create a session hash.
my ($session_hash, $session_salt) = $anvil->Account->_build_cookie_hash({uuid => $anvil->data->{cookie}{anvil_user_uuid}, offset => 0});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
session_hash => $session_hash,
session_salt => $session_salt,
}});
my $query = "
UPDATE
users
SET
user_session_salt = ".$anvil->data->{sys}{use_db_fh}->quote($session_salt).",
modified_date = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->data->{sys}{db_timestamp})."
WHERE
user_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($user_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0183", variables => { user => $anvil->data->{cgi}{username}{value} }});
$anvil->Account->_write_cookies({
debug => $debug,
hash => $session_hash,
uuid => $user_uuid,
});
}
else
{
# User DID NOT passed a valid username/password.
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0027"}) }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0184", variables => {
user_agent => $ENV{HTTP_USER_AGENT} ? $ENV{HTTP_USER_AGENT} : "#!string!log_0185!#",
source_ip => $ENV{REMOTE_ADDR} ? $ENV{REMOTE_ADDR} : "#!string!log_0185!#",
user => $anvil->data->{cgi}{username}{value},
}});
# Slow them down a bit...
sleep 5;
return(1);
}
return(0);
}
=head2 logout
This deletes the user's UUID and hash cookies, which effectively logs them out.
This methods takes no parameters and always returns C<< 0 >>.
=cut
sub logout
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
# Delete the user's cookie data. Sending nothing to '_write_cookies' does this.
$anvil->Account->_write_cookies({debug => $debug});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0179"});
return(0);
}
=head2 read_cookies
This method (tries to) read the user's cookies to see if their session is valid. If so, it will read in their account details.
This method takes no parameters.
Return codes;
=head3 0
The cookies were read, the account was validated and the user's details were loaded.
=head3 1
No cookie was found or read. The user needs to log in
=head3 2
There was a problem reading the user's UUID (it wasn't found in the database), so the cookies were deleted (via C<< Account->logout() >>. The user needs to log back in.
=head3 3
There user's hash is invalid, it is probably expired. The user has been logged out and needs to log back in.
=cut
sub read_cookies
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
# Read in any cookies
if (defined $ENV{HTTP_COOKIE})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "ENV{HTTP_COOKIE}" => $ENV{HTTP_COOKIE} }});
my @data = (split /; /, $ENV{HTTP_COOKIE});
foreach my $pair (@data)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { pair => $pair }});
my ($key, $value) = split/=/, $pair;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
key => $key,
value => $value,
}});
next if ((not defined $value) or ($value eq ""));
if ($key =~ /^anvil_/)
{
$anvil->data->{cookie}{$key} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "cookie::${key}" => $anvil->data->{cookie}{$key} }});
}
}
}
# Did we read a cookie?
if ((not defined $anvil->data->{cookie}{anvil_user_uuid}) or (not $anvil->data->{cookie}{anvil_user_uuid}))
{
# No cookie read.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0177"});
return(1);
}
elsif (not defined $anvil->data->{cookie}{anvil_user_hash})
{
$anvil->data->{cookie}{anvil_user_hash} = "";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"cookie::anvil_user_uuid" => $anvil->data->{cookie}{anvil_user_uuid},
"cookie::anvil_user_hash" => $anvil->data->{cookie}{anvil_user_hash},
}});
# Validate the cookie if there is a User UUID. Pick the random number up from the database.
my $query = "SELECT user_session_salt FROM users WHERE user_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->data->{cookie}{anvil_user_uuid}).";";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0124", variables => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if ($count < 1)
{
die;
# The user in the cookie isn't in the database. The user was deleted?
$anvil->Account->logout();
# Record the error message for the user.
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0023"}) }});
# We're done.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0178", variables => { uuid => $anvil->data->{cookie}{anvil_user_uuid} }});
return(2);
}
# Read in their "rand" value
$anvil->data->{users}{user_session_salt} = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->data->{users}{user_session_salt} = "" if not defined $anvil->data->{users}{user_session_salt};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "users::user_session_salt" => $anvil->data->{users}{user_session_salt} }});
# Generate a hash using today and yesterday's date.
my ($today_hash) = $anvil->Account->_build_cookie_hash({uuid => $anvil->data->{cookie}{anvil_user_uuid}, offset => 0});
my ($yesterday_hash) = $anvil->Account->_build_cookie_hash({uuid => $anvil->data->{cookie}{anvil_user_uuid}, offset => -86400});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
today_hash => $today_hash,
yesterday_hash => $yesterday_hash,
}});
# See if either hash matches what the user has stored.
if ($anvil->data->{cookie}{anvil_user_hash} eq $today_hash)
{
# Valid hash, user can proceed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0180"});
# Load the account details
$anvil->Account->read_details({debug => $debug});
}
elsif ($anvil->data->{cookie}{anvil_user_hash} eq $yesterday_hash)
{
# The hash was valid yesterday, so we'll update the cookie with today's hash and proceed
# (which also loads the user's details).
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0181"});
$anvil->Account->_write_cookies({
debug => $debug,
hash => $today_hash,
uuid => $anvil->data->{cookie}{anvil_user_uuid},
});
}
else
{
# The user's cookie is invalid, log the user out.
$anvil->Account->logout();
# Record the error message for the user.
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0024"}) }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0182"});
return(3);
}
return(0);
}
=head2 read_details
This method takes a user name and, if the user is found, reads in the details and sets C<< sys::user::<column names> >>. If the user is found, C<< 1 >> is returned. If not, C<< 0 >> is returned.
This method takes a user uuid and, if the user is found, reads in the details and sets C<< sys::users::<column names> >>. If the user is found, C<< 1 >> is returned. If not, C<< 0 >> is returned.
Parameters;
=head3 user_name (required)
=head3 user_uuid (optional)
This is the user name being searched for. It is case sensitive.
This is the user UUID being searched for. If it is not set, C<< cookie::anvil_user_uuid >>
=cut
sub read_details
@ -217,12 +545,18 @@ sub read_details
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $user_name = defined $parameter->{user_name} ? $parameter->{user_name} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_name => $user_name }});
my $user_uuid = defined $parameter->{user_uuid} ? $parameter->{user_uuid} : $anvil->data->{cookie}{anvil_user_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_uuid => $user_uuid }});
if (not $anvil->Validate->is_uuid({uuid => $user_uuid}))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "error_0025", variables => { uuid => $user_uuid }});
return(0);
}
my $query = "
SELECT
user_uuid,
user_name,
user_password_hash,
user_salt,
user_algorithm,
@ -234,7 +568,7 @@ SELECT
FROM
users
WHERE
user_name = ".$anvil->data->{sys}{use_db_fh}->quote($user_name)."
user_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($user_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
@ -247,9 +581,10 @@ WHERE
if (not $count)
{
# User doesn't exist.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "error_0026", variables => { uuid => $user_uuid }});
return(0);
}
my $user_uuid = $results->[0]->[0];
my $user_name = $results->[0]->[0];
my $user_password_hash = $results->[0]->[1];
my $user_salt = $results->[0]->[2];
my $user_algorithm = $results->[0]->[3];
@ -259,7 +594,7 @@ WHERE
my $user_is_experienced = $results->[0]->[7];
my $user_is_trusted = $results->[0]->[8];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
user_uuid => $user_uuid,
user_name => $user_name,
user_password_hash => $user_password_hash,
user_salt => $user_salt,
user_algorithm => $user_algorithm,
@ -269,30 +604,37 @@ WHERE
user_is_experienced => $user_is_experienced,
user_is_trusted => $user_is_trusted,
}});
$anvil->data->{sys}{user}{user_name} = $user_name;
$anvil->data->{sys}{user}{user_uuid} = $user_uuid;
$anvil->data->{sys}{user}{user_password_hash} = $user_password_hash,
$anvil->data->{sys}{user}{user_salt} = $user_salt,
$anvil->data->{sys}{user}{user_algorithm} = $user_algorithm,
$anvil->data->{sys}{user}{user_hash_count} = $user_hash_count,
$anvil->data->{sys}{user}{user_language} = $user_language,
$anvil->data->{sys}{user}{user_is_admin} = $user_is_admin,
$anvil->data->{sys}{user}{user_is_experienced} = $user_is_experienced,
$anvil->data->{sys}{user}{user_is_trusted} = $user_is_trusted,
$anvil->data->{sys}{users}{user_name} = $user_name;
$anvil->data->{sys}{users}{user_uuid} = $user_uuid;
$anvil->data->{sys}{users}{user_password_hash} = $user_password_hash,
$anvil->data->{sys}{users}{user_salt} = $user_salt,
$anvil->data->{sys}{users}{user_algorithm} = $user_algorithm,
$anvil->data->{sys}{users}{user_hash_count} = $user_hash_count,
$anvil->data->{sys}{users}{user_language} = $user_language,
$anvil->data->{sys}{users}{user_is_admin} = $user_is_admin,
$anvil->data->{sys}{users}{user_is_experienced} = $user_is_experienced,
$anvil->data->{sys}{users}{user_is_trusted} = $user_is_trusted,
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
'sys::user::user_name' => $anvil->data->{sys}{user}{user_name},
'sys::user::user_uuid' => $anvil->data->{sys}{user}{user_uuid},
'sys::user::user_password_hash' => $anvil->data->{sys}{user}{user_password_hash},
'sys::user::user_salt' => $anvil->data->{sys}{user}{user_salt},
'sys::user::user_algorithm' => $anvil->data->{sys}{user}{user_algorithm},
'sys::user::user_hash_count' => $anvil->data->{sys}{user}{user_hash_count},
'sys::user::user_language' => $anvil->data->{sys}{user}{user_language},
'sys::user::user_is_admin' => $anvil->data->{sys}{user}{user_is_admin},
'sys::user::user_is_experienced' => $anvil->data->{sys}{user}{user_is_experienced},
'sys::user::user_is_trusted' => $anvil->data->{sys}{user}{user_is_trusted},
'sys::users::user_name' => $anvil->data->{sys}{users}{user_name},
'sys::users::user_uuid' => $anvil->data->{sys}{users}{user_uuid},
'sys::users::user_password_hash' => $anvil->data->{sys}{users}{user_password_hash},
'sys::users::user_salt' => $anvil->data->{sys}{users}{user_salt},
'sys::users::user_algorithm' => $anvil->data->{sys}{users}{user_algorithm},
'sys::users::user_hash_count' => $anvil->data->{sys}{users}{user_hash_count},
'sys::users::user_language' => $anvil->data->{sys}{users}{user_language},
'sys::users::user_is_admin' => $anvil->data->{sys}{users}{user_is_admin},
'sys::users::user_is_experienced' => $anvil->data->{sys}{users}{user_is_experienced},
'sys::users::user_is_trusted' => $anvil->data->{sys}{users}{user_is_trusted},
}});
# Change the active language, if needed
if ($anvil->data->{sys}{users}{user_language})
{
# Switch to the user's language
$anvil->Words->language({set => $anvil->data->{sys}{users}{user_language}});
}
return(1);
}
@ -325,7 +667,7 @@ sub validate_password
my $valid = 0;
my $hash = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
user => $user,
}});
@ -441,4 +783,128 @@ WHERE
return($valid);
}
# =head3
#
# Private Functions;
#
# =cut
#############################################################################################################
# Private functions #
#############################################################################################################
=head2 _build_cookie_hash
This takes a (user) UUID and offset (stated as seconds) and builds a hash approporiate for use in cookies (or a test hash to validate a read cookie hash).
Parameters;
=head3 offset (optional, default '0')
This is used to offset the date when generating the date part of the string to hash. It is passed as-is directly to C<< Get->date_and_time >>.
=head3 user_agent (optional, default 'HTTP_USER_AGENT' environment variable)
This is the user agent to use when generating the string to hash.
=head3 uuid (optional, default 'cookie::anvil_user_uuid')
This is the UUID to use when generating the string to hash. Generally it is the user's UUID.
=cut
sub _build_cookie_hash
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $offset = defined $parameter->{offset} ? $parameter->{offset} : 0;
my $user_agent = defined $parameter->{user_agent} ? $parameter->{user_agent} : $ENV{HTTP_USER_AGENT};
my $uuid = defined $parameter->{uuid} ? $parameter->{uuid} : $anvil->data->{cookie}{anvil_user_uuid};
# I know I could do chained conditionals, but it gets hard to read.
$user_agent = "" if not defined $user_agent;
$uuid = "" if not defined $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
offset => $offset,
user_agent => $user_agent,
uuid => $uuid,
}});
my $date = $anvil->Get->date_and_time({date_only => 1, offset => $offset});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { date => $date }});
my $session_string = $uuid.$date.$user_agent;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { session_string => $session_string }});
# Generate a hash, but unike normal passwords, we won't re-encrypt it.
my $answer = $anvil->Account->encrypt_password({password => $session_string, hash_count => 0});
my $hash = $answer->{user_password_hash};
my $salt = $answer->{user_salt};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
hash => $hash,
salt => $salt,
}});
return($hash, $salt);
}
=head2 _write_cookies
This sets (or clears) the user's cookies.
Parameters;
=head3 hash (optional)
This is the hash to use for the session. If it is blank, it will log the user out.
=head3 uuid (optional)
This is the UUID of the user. If it is blank, it will log the user out.
=cut
sub _write_cookies
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $hash = defined $parameter->{hash} ? $parameter->{hash} : "";
my $uuid = defined $parameter->{uuid} ? $parameter->{uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
hash => $hash,
uuid => $uuid,
}});
# If we have a users ID, load the user details
if (($hash) && ($uuid))
{
# Write the cookies
print "Set-Cookie:anvil_user_uuid=".$uuid.";\n";
print "Set-Cookie:anvil_user_hash=".$hash.";\n";
# Load the user's details
$anvil->Account->read_details({
debug => $debug,
user_uuid => $uuid});
# Update the active language, if needed.
if ($anvil->data->{sys}{users}{user_language})
{
# Switch to the user's language
$anvil->Words->language({set => $anvil->data->{sys}{users}{user_language}});
}
}
else
{
print "Set-Cookie:anvil_user_uuid=; expires=-1d;\n";
print "Set-Cookie:anvil_user_hash=; expires=-1d;\n";
}
return(0);
}
1;

@ -676,7 +676,7 @@ sub connect
port => $port,
name => $name,
user => $user,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
}});
# If not set, we will always ping before connecting.
@ -711,7 +711,7 @@ sub connect
port => $port,
name => $name,
user => $user,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
}});
### TODO: Can we do a telnet port ping with a short timeout instead of a shell ping call?
@ -975,14 +975,14 @@ sub connect
# Report any failed DB connections
foreach my $uuid (@{$failed_connections})
{
my $database_name = defined $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "--";
my $database_user = defined $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "--";
my $database_name = defined $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "#!string!log_0185!#";
my $database_user = defined $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "#!string!log_0185!#";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"database::${uuid}::host" => $anvil->data->{database}{$uuid}{host},
"database::${uuid}::port" => $anvil->data->{database}{$uuid}{port},
"database::${uuid}::name" => $database_name,
"database::${uuid}::user" => $database_user,
"database::${uuid}::password" => $anvil->Log->secure ? $anvil->data->{database}{$uuid}{password} : "--",
"database::${uuid}::password" => $anvil->Log->secure ? $anvil->data->{database}{$uuid}{password} : "#!string!log_0186!#",
}});
# Copy my alert hash before I delete the uuid.
@ -1034,14 +1034,14 @@ sub connect
# Send an 'all clear' message if a now-connected DB previously wasn't.
foreach my $uuid (@{$successful_connections})
{
my $database_name = defined $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "--";
my $database_user = defined $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "--";
my $database_name = defined $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "#!string!log_0185!#";
my $database_user = defined $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "#!string!log_0185!#";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"database::${uuid}::host" => $anvil->data->{database}{$uuid}{host},
"database::${uuid}::port" => $anvil->data->{database}{$uuid}{port},
"database::${uuid}::name" => $database_name,
"database::${uuid}::user" => $database_user,
"database::${uuid}::password" => $anvil->Log->secure ? $anvil->data->{database}{$uuid}{password} : "--",
"database::${uuid}::password" => $anvil->Log->secure ? $anvil->data->{database}{$uuid}{password} : "#!string!log_0186!#",
}});
### TODO: Is this still an issue? If so, then we either need to require that the DB host
@ -3373,7 +3373,7 @@ sub insert_or_update_users
line => $line,
user_uuid => $user_uuid,
user_name => $user_name,
user_password_hash => (($anvil->Log->secure) or ($user_salt)) ? $user_password_hash : "--" ,
user_password_hash => (($anvil->Log->secure) or ($user_salt)) ? $user_password_hash : "#!string!log_0186!#" ,
user_salt => $user_salt,
user_algorithm => $user_algorithm,
user_hash_count => $user_hash_count,
@ -3423,7 +3423,7 @@ sub insert_or_update_users
$user_algorithm = $answer->{user_algorithm};
$user_hash_count = $answer->{user_hash_count};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
user_password_hash => (($anvil->Log->secure) or ($user_salt)) ? $user_password_hash : "--" ,
user_password_hash => (($anvil->Log->secure) or ($user_salt)) ? $user_password_hash : "#!string!log_0186!#" ,
user_salt => $user_salt,
user_algorithm => $user_algorithm,
user_hash_count => $user_hash_count,
@ -4343,7 +4343,7 @@ sub query
uuid => $uuid,
"cache::db_fh::${uuid}" => $anvil->data->{cache}{db_fh}{$uuid},
line => $line,
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "--",
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "#!string!log_0186!#",
secure => $secure,
source => $source,
}});
@ -4390,14 +4390,14 @@ sub query
# Do the query.
my $DBreq = $anvil->data->{cache}{db_fh}{$uuid}->prepare($query) or $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0075", variables => {
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "--",
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "#!string!log_0186!#",
server => $say_server,
db_error => $DBI::errstr,
}});
# Execute on the query
$DBreq->execute() or $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0076", variables => {
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "--",
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "#!string!log_0186!#",
server => $say_server,
db_error => $DBI::errstr,
}});
@ -4915,7 +4915,7 @@ sub write
uuid => $uuid,
"cache::db_fh::${uuid}" => $anvil->data->{cache}{db_fh}{$uuid},
line => $line,
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "--",
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "#!string!log_0186!#",
secure => $secure,
source => $source,
reenter => $reenter,
@ -5064,7 +5064,7 @@ sub write
# Do the do.
$anvil->data->{cache}{db_fh}{$uuid}->do($query) or $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0090", variables => {
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "--",
query => ((not $secure) or (($secure) && (not $anvil->Log->secure))) ? $query : "#!string!log_0186!#",
server => $say_server,
db_error => $DBI::errstr,
}});
@ -5275,14 +5275,14 @@ sub _find_behind_databases
my $source_updated_time = 0;
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{database}})
{
my $database_name = defined $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "--";
my $database_user = defined $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "--";
my $database_name = defined $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : "#!string!log_0185!#";
my $database_user = defined $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : "#!string!log_0185!#";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"database::${uuid}::host" => $anvil->data->{database}{$uuid}{host},
"database::${uuid}::port" => $anvil->data->{database}{$uuid}{port},
"database::${uuid}::name" => $database_name,
"database::${uuid}::user" => $database_user,
"database::${uuid}::password" => $anvil->Log->secure ? $anvil->data->{database}{$uuid}{password} : "--",
"database::${uuid}::password" => $anvil->Log->secure ? $anvil->data->{database}{$uuid}{password} : "#!string!log_0186!#",
}});
# Loop through the tables in this DB. For each table, we'll record the most recent time

@ -125,7 +125,7 @@ sub anvil_version
my $target = defined $parameter->{target} ? $parameter->{target} : "local";
my $version = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
port => $port,
remote_user => $remote_user,
target => $target,
@ -318,7 +318,7 @@ sub cgi
if ((($variable =~ /passwd/) or ($variable =~ /password/)) && (not $anvil->Log->secure))
{
# This is a password and we're not logging sensitive data, obfuscate it.
$censored_value = "--";
$censored_value = "#!string!log_0186!#";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
"cgi::${variable}::$say_value" => $censored_value,
@ -375,6 +375,7 @@ sub date_and_time
my $time_only = defined $parameter->{time_only} ? $parameter->{time_only} : 0;
my $date_only = defined $parameter->{date_only} ? $parameter->{date_only} : 0;
# NOTE: This is used too early for normal error handling.
# Are things sane?
if ($use_time =~ /D/)
{

@ -294,9 +294,9 @@ sub call
# NOTE: The shell call might contain sensitive data, so we show '--' if 'secure' is set and $anvil->Log->secure is not.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $log_level, list => {
'close' => $close,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
secure => $secure,
shell_call => ((not $anvil->Log->secure) && ($secure)) ? "--" : $shell_call,
shell_call => ((not $anvil->Log->secure) && ($secure)) ? "#!string!log_0186!#" : $shell_call,
ssh_fh => $ssh_fh,
start_time => $start_time,
remote_user => $remote_user,
@ -467,7 +467,7 @@ sub call
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $log_level, list => {
remote_user => $remote_user,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
}});
if (not $ssh_fh->auth_password($remote_user, $password))
{

@ -144,7 +144,7 @@ sub backup
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
fatal => $fatal,
port => $port,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
target => $target,
remote_user => $remote_user,
source_file => $source_file,
@ -609,7 +609,7 @@ sub copy_file
my $target = defined $parameter->{target} ? $parameter->{target} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
overwrite => $overwrite,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
remote_user => $remote_user,
source_file => $source_file,
target_file => $target_file,
@ -904,7 +904,7 @@ sub make_directory
group => $group,
mode => $mode,
port => $port,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
remote_user => $remote_user,
target => $target,
user => $user,
@ -1234,7 +1234,7 @@ sub read_file
file => $file,
force_read => $force_read,
port => $port,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
remote_user => $remote_user,
secure => $secure,
target => $target,
@ -1546,7 +1546,7 @@ sub rsync
my $failed = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
destination => $destination,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
port => $port,
source => $source,
switches => $switches,
@ -1860,11 +1860,11 @@ sub update_config
my $update = 0;
my $new_file = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
port => $port,
secure => $secure,
target => $target,
value => ((not $secure) or ($anvil->Log->secure)) ? $value : "--",
value => ((not $secure) or ($anvil->Log->secure)) ? $value : "#!string!log_0186!#",
variable => $variable,
remote_user => $remote_user,
}});
@ -1901,7 +1901,7 @@ sub update_config
my $is_secure = $this_variable =~ /passw/i ? 1 : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
this_variable => $this_variable,
this_value => ((not $is_secure) or ($anvil->Log->secure)) ? $this_value : "--",
this_value => ((not $is_secure) or ($anvil->Log->secure)) ? $this_value : "#!string!log_0186!#",
}});
if ($this_variable eq $variable)
{
@ -2060,7 +2060,7 @@ sub write_file
mode => $mode,
overwrite => $overwrite,
port => $port,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
secure => $secure,
target => $target,
user => $user,
@ -2326,7 +2326,7 @@ sub _create_rsync_wrapper
my $target = defined $parameter->{target} ? $parameter->{target} : "";
my $password = defined $parameter->{password} ? $parameter->{password} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
target => $target,
}});

@ -251,8 +251,8 @@ sub change_shell_user_password
target => $target,
port => $port,
remote_user => $remote_user,
new_password => $anvil->Log->secure ? $new_password : "--",
password => $anvil->Log->secure ? $password : "--",
new_password => $anvil->Log->secure ? $new_password : "#!string!log_0186!#",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
}});
# Do I have a user?
@ -1335,7 +1335,7 @@ sub ping
count => $count,
fragment => $fragment,
payload => $payload,
password => $anvil->Log->secure ? $password : "--",
password => $anvil->Log->secure ? $password : "#!string!log_0186!#",
ping => $ping,
port => $port,
remote_user => $remote_user,

@ -26,8 +26,7 @@ if (($running_directory =~ /^\./) && ($ENV{PWD}))
my $anvil = Anvil::Tools->new();
# Print the html headers, with a new line to break the header from the body.
print $anvil->Template->get({file => "shared.html", name => "http_headers"})."\n";
### NOTE: We'll print the headers only when we need to. If we print them hear, it will block cookies being set.
# Set the log level to 2. Setting 3 slows he program down a LOT.
$anvil->Log->level({set => 2});
@ -51,6 +50,7 @@ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "
if (not $connections)
{
# No databases, exit.
print $anvil->Template->get({file => "shared.html", name => "http_headers"})."\n";
print $anvil->Words->string({key => "error_0003"});
$anvil->nice_exit({exit_code => 2});
}
@ -107,6 +107,7 @@ my $template = $anvil->Template->get({file => "main.html", name => "master", var
footer => $footer,
}});
print $anvil->Template->get({file => "shared.html", name => "http_headers"})."\n";
print $template;
$anvil->nice_exit({exit_code => 0});
@ -121,7 +122,65 @@ sub process_task
{
my ($anvil) = @_;
my $body = "hi";
# Is the user trying to log in?
my $body = "hi";
my $logged_in = 0;
if ((defined $anvil->data->{cgi}{login}) && ($anvil->data->{cgi}{login}{value}))
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::login::value" => $anvil->data->{cgi}{login}{value} }});
# Woot!
my $failed = $anvil->Account->login({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { failed => $failed }});
if (not $failed)
{
$logged_in = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { logged_in => $logged_in }});
}
}
else
{
# Is the user logged in?
# 0 - The cookies were read, the account was validated and the user's details were loaded.
# 1 - No cookie was found or read. The user needs to log in
# 2 - There was a problem reading the user's UUID (it wasn't found in the database), so the
# cookies were deleted (via C<< Account->_logout() >>. The user needs to log back in.
# 3 - There user's hash is invalid, it is probably expired. The user has been logged out and
# needs to log back in.
my $cookie_problem = $anvil->Account->read_cookies({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cookie_problem => $cookie_problem }});
if (not $cookie_problem)
{
$logged_in = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { logged_in => $logged_in }});
}
}
# Show the login screen, if the user isn't logged in.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { logged_in => $logged_in }});
if (not $logged_in)
{
$body = $anvil->Template->get({file => "main.html", name => "striker-login", variables => {
user => $anvil->data->{cgi}{username}{value},
password => "",
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { body => $body }});
return($body);
}
# If we're here, the user is logged in!
$body = "logged in as: [".$anvil->data->{sys}{users}{user_name}."]\n";
# $anvil->data->{sys}{users}{user_name} = $user_name;
# $anvil->data->{sys}{users}{user_uuid} = $user_uuid;
# $anvil->data->{sys}{users}{user_password_hash} = $user_password_hash,
# $anvil->data->{sys}{users}{user_salt} = $user_salt,
# $anvil->data->{sys}{users}{user_algorithm} = $user_algorithm,
# $anvil->data->{sys}{users}{user_hash_count} = $user_hash_count,
# $anvil->data->{sys}{users}{user_language} = $user_language,
# $anvil->data->{sys}{users}{user_is_admin} = $user_is_admin,
# $anvil->data->{sys}{users}{user_is_experienced} = $user_is_experienced,
# $anvil->data->{sys}{users}{user_is_trusted} = $user_is_trusted,
return($body);
}

@ -10,6 +10,16 @@ Colours;
- Footer text: #515151
*/
.login {
width: 600px;
height: 50px;
position: fixed;
margin-left: -300px; /* half of width */
margin-top: -25px; /* half of height */
top: 50%;
left: 50%;
}
.error_message {
border-left: 3px solid #d02724;
border-right: 3px solid #d02724;
@ -28,7 +38,7 @@ input[type=text].input_alert, input[type=number].input_alert, select.input_alert
border: 1px solid #ff3f3f;
}
input[type=text], input[type=number] {
input[type=text], input[type=number], input[type=password] {
width: 100%;
padding: 6px 10px;
margin: 2px 0;
@ -54,6 +64,10 @@ select {
font-size: 1.0em;
}
.code {
font-family: 'Dejavu Sans Mono', Courier;
}
body {
font-family: 'Dejavu Sans', Arial, Helvetica, Verdana, Sans-Serif;
background-image: url("/skins/alteeve/images/Texture.jpg");
@ -175,6 +189,7 @@ td {
.subtle_text {
color: #9D9D9D;
text-align: left;
font-size: 0.9em;
}
.header {

@ -330,6 +330,38 @@
</table>
<!-- end striker-offline -->
<!-- start striker-login -->
<table class="login"">
<form name="striker_login" action="">
<div id="striker_login">
<tr>
<td>
<input type="text" name="username" id="username" value="#!variable!user!#" placeholder="#!string!striker_0050!#" />
</td>
<td>
&nbsp;
</td>
<td>
<input type="password" name="password" id="password" value="#!variable!password!#" placeholder="#!string!striker_0051!#" />
</td>
<td>
&nbsp;
</td>
<td>
<input type="submit" name="login" id="login" value="#!string!striker_0049!#">
</td>
</tr>
<tr>
<td colspan="5" class="subtle_text" style="text-align: center;">
#!string!message_0032!#
</td>
</tr>
</div>
<input type="hidden" name="cgi_list" id="cgi_list" value="username,password,login">
</form>
</table>
<!-- end striker-login -->
<!-- start step3_bonded_interface -->
<tr>
<td class="column_row_name">

@ -57,6 +57,7 @@ NOTE: You must update the password of any other system using this host's
</key>
<key name="message_0030">Failed to write the new password to the temporary file: [#!variable!file!#]. Please check the logs for details.</key>
<key name="message_0031">Beginning configuration of local system.</key>
<key name="message_0032"><![CDATA[Forgot your password?<br />Use '<span class="code">anvil-change-password</span>' from the console to reset it.]]></key>
<!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key>
@ -268,6 +269,16 @@ The database connection error was:
<key name="log_0174"><![CDATA[[ Error ] - Asked to update the variable: [#!variable!variable!#] in the configuration file: [#!variable!file!#], but that variable was not found.]]></key>
<key name="log_0175"><![CDATA[[ Error ] - Asked to update the variable: [#!variable!variable!#] in the configuration file: [#!variable!file!#] on the host: [#!variable!target!#], but that variable was not found.]]></key>
<key name="log_0176">The IP hash key: [#!variable!ip_key!#] does not exist, skipping it.</key>
<key name="log_0177">No cookies were read, the use is not logged in.</key>
<key name="log_0178">The user's UUID: [#!variable!uuid!#] was read, but it didn't match any known users.</key>
<key name="log_0179">The user has been logged out.</key>
<key name="log_0180">The user hash in the user's cookie is valid.</key>
<key name="log_0181">The user hash in the user's cookie was valid yesterday, updating the stored hash and allowing the user to proceed.</key>
<key name="log_0182">The user hash in the user's coolkie is invalid. It is probably expired.</key>
<key name="log_0183">The user: [#!variable!user!#] logged in successfully.</key>
<key name="log_0184">Theew was a failed login attempt from: [#!variable!user_agent!#], trying to log in as: [#!variable!user!#]. log in rejected.</key>
<key name="log_0185"><![CDATA[<unknown>]]></key> <!-- Used in some cases when a variable isn't known -->
<key name="log_0186"><![CDATA[<supressed>]]></key> <!-- Used in some cases when a variable isn't known -->
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key>
@ -350,6 +361,9 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="striker_0046">Offline...</key>
<key name="striker_0047">A job to reconfigure this Striker is underway. It is: [#!variable!percent!#%] done. It last updated its progress at: [#!variable!timestamp!#] (#!variable!seconds_ago!# seconds ago). Please try again shortly.</key>
<key name="striker_0048">This indicates that this machine has been configured. After an initial install, this variable won't exist. If it is set to '0', it will trigger a reconfiguration of the local system.</key>
<key name="striker_0049">Log in</key>
<key name="striker_0050">User name</key>
<key name="striker_0051">Password</key>
<!-- Strings used by jobs -->
<key name="job_0001">Configure Network</key>
@ -381,6 +395,11 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="error_0020">The: [#!variable!field!#] field can't be empty.</key>
<key name="error_0021">The prefix needs to be set, and be between 1 and 5 characters long.</key>
<key name="error_0022">The: [#!variable!field!#] must be a positive integer.</key>
<key name="error_0023">There was a problem reading your session details. To be safe, you have been logged out. Please try logging back in.</key>
<key name="error_0024">It appears that your session has expired. To be safe, you have been logged out. Please try logging back in.</key>
<key name="error_0025">The user ID passed in to Account->read_details: [#!variable!uuid!#] is not a valid UUID.</key>
<key name="error_0026">The user ID passed in to Account->read_details: [#!variable!uuid!#] was not found in the database.</key>
<key name="error_0027">Login failed, please try again.</key>
<!-- These are works and strings used by javascript/jqery -->
<key name="js_0001">Up</key>

@ -220,7 +220,7 @@ sub update_local_passwords
print $anvil->Words->string({key => "message_0026", variables => { user => $user }});
my $query = "ALTER ROLE ".$user." WITH PASSWORD ".$dbh->quote($anvil->data->{switches}{'new-password'});
$dbh->do($query) or $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0090", variables => {
query => $anvil->Log->secure ? $query : "--",
query => $anvil->Log->secure ? $query : "#!string!log_0186!#",
server => "localhost",
db_error => $DBI::errstr,
}});

@ -44,6 +44,7 @@ CREATE TABLE users (
user_uuid uuid not null primary key, -- This is the single most important record in Anvil!. Everything links back to here.
user_name text not null,
user_password_hash text not null, -- A user without a password is disabled.
user_session_salt text not null, -- This is used when generating a session hash for a user when they log in.
user_salt text not null, -- This is used to enhance the security of the user's password.
user_algorithm text not null, -- This is the algorithm used to encrypt the password and salt.
user_hash_count text not null, -- This is the number of times that the password+salt was re-hashed through the algorithm.
@ -60,6 +61,7 @@ CREATE TABLE history.users (
user_uuid uuid,
user_name text,
user_password_hash text,
user_session_salt text,
user_salt text,
user_algorithm text,
user_hash_count text,
@ -81,6 +83,7 @@ BEGIN
(user_uuid,
user_name,
user_password_hash,
user_session_salt,
user_salt,
user_algorithm,
user_hash_count,
@ -93,6 +96,7 @@ BEGIN
(history_users.user_uuid,
history_users.user_name,
history_users.user_password_hash,
history_users.user_session_salt,
history_users.user_salt,
history_users.user_algorithm,
history_users.user_hash_count,

Loading…
Cancel
Save