default to a session cookie instead of setting an explicit timeout, weird timezone...
[freeside.git] / FS / FS / Auth / internal.pm
index 5d9170e..92dff03 100644 (file)
@@ -2,44 +2,87 @@ package FS::Auth::internal;
 #use base qw( FS::Auth );
 
 use strict;
-use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash);
+use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash en_base64 de_base64);
 use FS::Record qw( qsearchs );
 use FS::access_user;
 
 sub authenticate {
-  my($self, $username, $check_password ) = @_;
+  my($self, $username, $check_password, $totp_code ) = @_;
 
-  my $access_user = qsearchs('access_user', { 'username' => $username,
-                                              'disabled' => '',
-                                            }
-                            )
+  my $access_user =
+    ref($username) ? $username
+                   : qsearchs('access_user', { 'username' => $username,
+                                               'disabled' => '',
+                                             }
+                             )
     or return 0;
 
+  my $pw_check;
   if ( $access_user->_password_encoding eq 'bcrypt' ) {
 
     my( $cost, $salt, $hash ) = split(',', $access_user->_password);
 
-    my $check_hash = bcrypt_hash( { key_nul => 1,
-                                    cost    => $cost,
-                                    salt    => $salt,
-                                  },
-                                  $check_password
-                                );
+    my $check_hash = en_base64( bcrypt_hash( { key_nul => 1,
+                                               cost    => $cost,
+                                               salt    => de_base64($salt),
+                                             },
+                                             $check_password
+                                           )
+                              );
 
-    $hash eq $check_hash;
+    $pw_check = $hash eq $check_hash;
 
-  } else { 
+  } else {
 
     return 0 if $access_user->_password eq 'notyet'
              || $access_user->_password eq '';
 
-    $access_user->_password eq $check_password;
+    $pw_check = $access_user->_password eq $check_password;
 
   }
 
+  return $pw_check if ! $pw_check || ! length($access_user->totp_secret32);
+
+  #2fa
+  $access_user->google_auth->verify( $totp_code, 1 );
+}
+
+sub autocreate { 0; }
+
+sub change_password {
+  my($self, $access_user, $new_password) = @_;
+
+  # do nothing if the password is unchanged
+  #XXX breaks password changes in employee edit ($access_user object already
+  # has new [plaintext] password)
+  #return if $self->authenticate( $access_user, $new_password );
+
+  $self->change_password_fields( $access_user, $new_password );
+
+  $access_user->replace;
+
 }
 
-#sub change_password {
-#}
+sub change_password_fields {
+  my($self, $access_user, $new_password) = @_;
+
+  $access_user->_password_encoding('bcrypt');
+
+  my $cost = 8;
+
+  my $salt = pack( 'C*', map int(rand(256)), 1..16 );
+
+  my $hash = bcrypt_hash( { key_nul => 1,
+                            cost    => $cost,
+                            salt    => $salt,
+                          },
+                          $new_password,
+                        );
+
+  $access_user->_password(
+    join(',', $cost, en_base64($salt), en_base64($hash) )
+  );
+
+}
 
 1;