RT#29354: Password Security in Email [customer fields, images, js files]
[freeside.git] / FS / FS / Password_Mixin.pm
index bcad546..834fd6f 100644 (file)
@@ -61,17 +61,46 @@ sub is_password_allowed {
   $error = 'Invalid password - ' . $error if $error;
   return $error if $error;
 
-  #check against known usernames
-  my @disallowed_names = $self->password_disallowed_names;
-  foreach my $noname (@disallowed_names) {
-    if ($password =~ /$noname/i) {
-      #keeping message ambiguous to avoid leaking personal info
-      return 'Password contains a disallowed word';
-    }
-  }
+  #check against service fields
+  $error = $self->password_svc_check($password);
+  return $error if $error;
 
   return '' unless $self->get($self->primary_key); # for validating new passwords pre-insert
 
+  #check against customer fields
+  my $cust_main = $self->cust_main;
+  if ($cust_main) {
+    my @words;
+    # words from cust_main
+    foreach my $field ( qw( last first daytime night fax mobile ) ) {
+        push @words, split(/\W/,$cust_main->get($field));
+    }
+    # words from cust_location
+    foreach my $loc ($cust_main->cust_location) {
+      foreach my $field ( qw(address1 address2 city county state zip) ) {
+        push @words, split(/\W/,$loc->get($field));
+      }
+    }
+    # words from cust_contact & contact_phone
+    foreach my $contact (map { $_->contact } $cust_main->cust_contact) {
+      foreach my $field ( qw(last first) ) {
+        push @words, split(/\W/,$contact->get($field));
+      }
+      # not hugely useful right now, hyphenless stored values longer than password max,
+      # but max will probably be increased eventually...
+      foreach my $phone ( qsearch('contact_phone', {'contactnum' => $contact->contactnum}) ) {
+        push @words, split(/\W/,$phone->get('phonenum'));
+      }
+    }
+    # do the actual checking
+    foreach my $word (@words) {
+      next unless length($word) > 2;
+      if ($password =~ /$word/i) {
+        return qq(Password contains account information '$word');
+      }
+    }
+  }
+
   my $no_reuse = 3;
   # allow override here if we really must
 
@@ -107,15 +136,15 @@ sub is_password_allowed {
   '';
 }
 
-=item password_disallowed_names
+=item password_svc_check
 
-Override to return a list additional words (eg usernames) not
-to be used by passwords on this service.
+Override to run additional service-specific password checks.
 
 =cut
 
-sub password_disallowed_names {
-  return ();
+sub password_svc_check {
+  my ($self, $password) = @_;
+  return '';
 }
 
 =item password_history_key