diff --git a/Anvil/Tools/Account.pm b/Anvil/Tools/Account.pm
index 587e0c6a..953a52f9 100755
--- a/Anvil/Tools/Account.pm
+++ b/Anvil/Tools/Account.pm
@@ -13,7 +13,7 @@ my $THIS_FILE = "Account.pm";
### Methods;
# encrypt_password
-#
+# validate_password
=pod
@@ -208,4 +208,149 @@ sub encrypt_password
return($answer);
}
+=head2 validate_password
+
+This method takes a user name and password and checks to see if the password matches.
+
+If the password is wrong, or if the user isn't found, C<< 0 >> is returned. If the password matches, C<< 1 >> is returned.
+
+Parameters;
+
+=head3 password (required)
+
+This is the password to test.
+
+=head3 user (required)
+
+This is the user whose password we're testing.
+
+=cut
+sub validate_password
+{
+ my $self = shift;
+ my $parameter = shift;
+ my $anvil = $self->parent;
+ my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
+
+ my $password = defined $parameter->{password} ? $parameter->{password} : "";
+ my $user = defined $parameter->{user} ? $parameter->{user} : "";
+ my $valid = 0;
+ my $hash = "";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ password => $anvil->Log->secure ? $password : "--",
+ user => $user,
+ }});
+
+ if (not $password)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Account->validate_password()", parameter => "password" }});
+ return($valid);
+ }
+ if (not $user)
+ {
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Account->validate_password()", parameter => "user" }});
+ return($valid);
+ }
+
+ my $query = "
+SELECT
+ user_password,
+ user_salt,
+ user_algorithm,
+ user_hash_count
+FROM
+ users
+WHERE
+ user_name = ".$anvil->data->{sys}{use_db_fh}->quote($user)."
+;";
+ $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->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0172", variables => { user => $user }});
+ return($valid);
+ }
+
+ my $user_password = $results->[0]->[0];
+ my $user_salt = $results->[0]->[1];
+ my $user_algorithm = $results->[0]->[2];
+ my $user_hash_count = $results->[0]->[3];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ user_password => $user_password,
+ user_salt => $user_salt,
+ user_algorithm => $user_algorithm,
+ user_hash_count => $user_hash_count,
+ }});
+
+ if ($user_algorithm eq "sha256" )
+ {
+ $hash = sha256_base64($password.$user_salt);
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { hash => $hash }});
+
+ if ($user_hash_count > 0)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_hash_count => $user_hash_count }});
+ for (1..$user_hash_count)
+ {
+ $hash = sha256_base64($hash);
+ }
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { hash => $hash }});
+ }
+ }
+ elsif ($user_algorithm eq "sha384" )
+ {
+ $hash = sha384_base64($password.$user_salt);
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { hash => $hash }});
+
+ if ($user_hash_count > 0)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_hash_count => $user_hash_count }});
+ for (1..$user_hash_count)
+ {
+ $hash = sha384_base64($hash);
+ }
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { hash => $hash }});
+ }
+ }
+ elsif ($user_algorithm eq "sha512" )
+ {
+ $hash = sha512_base64($password.$user_salt);
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { hash => $hash }});
+
+ if ($user_hash_count > 0)
+ {
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user_hash_count => $user_hash_count }});
+ for (1..$user_hash_count)
+ {
+ $hash = sha512_base64($hash);
+ }
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { hash => $hash }});
+ }
+ }
+ else
+ {
+ # Bad algorith.
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0173", variables => { user_algorithm => $user_algorithm }});
+ return($valid);
+ }
+
+ # Test.
+ if ($hash eq $user_password)
+ {
+ # Good password.
+ $valid = 1;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { valid => $valid }});
+ }
+
+ return($valid);
+}
+
1;
diff --git a/share/words.xml b/share/words.xml
index 106ae117..4b7bffbb 100644
--- a/share/words.xml
+++ b/share/words.xml
@@ -251,6 +251,8 @@ The database connection error was:
Failed to copy the file: [#!variable!source_file!#] to: [#!variable!target_file!#] on the target: [#!variable!target!#] as: [#!variable!remote_user!#]. The error (if any) was: [#!variable!error!#] and the output (if any) was: [#!variable!output!#].
copy_file() was asked to copy: [#!variable!source_file!#] to: [#!variable!target_file!#], but the target's parent directory doesn't exist and we were unable to create it.]]>
encrypt_password() tried to use the algorithm: [#!variable!algorithm!#], which is not recognized. Only 'sha256', 'sha384' and 'sha512' are currently supported. The desired algorithm can be set via 'sys::password::algorithm'.]]>
+
+
Test
diff --git a/tools/anvil-change-password b/tools/anvil-change-password
index b60501e1..1c3f8932 100755
--- a/tools/anvil-change-password
+++ b/tools/anvil-change-password
@@ -58,18 +58,26 @@ if (not $connections)
$anvil->nice_exit({exit_code => 2});
}
-my $user_uuid = $anvil->Database->insert_or_update_users({
- debug => 2,
- user_name => "admin",
- user_password => "Initial2",
- user_salt => "",
- user_algorithm => "",
- user_hash_count => "",
- user_is_admin => 1,
- user_is_experienced => 1,
- user_is_trusted => 1,
+my $user = "admin";
+my $password = "Initial2";
+# my $user_uuid = $anvil->Database->insert_or_update_users({
+# debug => 2,
+# user_name => $user,
+# user_password => $password,
+# user_salt => "",
+# user_algorithm => "",
+# user_hash_count => "",
+# user_is_admin => 1,
+# user_is_experienced => 1,
+# user_is_trusted => 1,
+# });
+# print "User name: [".$user."], UUID: [".$user_uuid."]\n";
+my $valid = $anvil->Account->validate_password({
+ debug => 2,
+ user => $user,
+ password => $password,
});
-print "User UUID: [".$user_uuid."]\n";
+print "Password validated? [".$valid."].\n";
exit;
# The order that we pick up the new password is;