From e21c851c13a9d09f4d7fcbff342db7c10a195bb3 Mon Sep 17 00:00:00 2001 From: Jamie Cameron Date: Fri, 8 Feb 2013 18:06:17 -0800 Subject: [PATCH] use words file to validate passwords https://www.virtualmin.com/node/25300 --- useradmin/config.info | 1 + useradmin/user-lib.pl | 61 ++++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/useradmin/config.info b/useradmin/config.info index 6f5d1d098..e6d2af9fc 100644 --- a/useradmin/config.info +++ b/useradmin/config.info @@ -50,6 +50,7 @@ membox=Edit group members using,1,1-Text box,0-User selector line5=Password restrictions,11 passwd_min=Minimum password length,3,No minimum passwd_dict=Prevent dictionary word passwords?,1,1-Yes,0-No +dict_file=Files containing dictionary words,3,Use system defaults passwd_re=Perl regexp to check password against,3,None passwd_redesc=Human-readable description of regexp,3,Just use regexp passwd_same=Prevent passwords containing username?,1,1-Yes,0-No diff --git a/useradmin/user-lib.pl b/useradmin/user-lib.pl index b8b978661..5c29b817c 100755 --- a/useradmin/user-lib.pl +++ b/useradmin/user-lib.pl @@ -1537,30 +1537,9 @@ if ($re && !eval { $pass =~ /^$re$/ }) { if ($config{'passwd_same'}) { return &text('usave_epasswd_same') if ($pass =~ /\Q$username\E/i); } -if ($config{'passwd_dict'} && $pass =~ /^[A-Za-z\'\-]+$/ && - (&has_command("ispell") || &has_command("spell"))) { - # Call spell or ispell to check for dictionary words - local $temp = &transname(); - open(TEMP, ">$temp"); - print TEMP $pass,"\n"; - close(TEMP); - if (&has_command("ispell")) { - open(SPELL, "ispell -a <$temp |"); - while() { - if (/^(#|\&|\?)/) { - $unknown++; - } - } - close(SPELL); - } - else { - open(SPELL, "spell <$temp |"); - local $line = ; - $unknown++ if ($line); - close(SPELL); - } - unlink($temp); - return &text('usave_epasswd_dict') if (!$unknown); +if ($config{'passwd_dict'} && $pass =~ /^[A-Za-z\'\-]+$/) { + # Check if dictionary word + return &text('usave_epasswd_dict') if (&is_dictionary_word($pass)); } if ($config{'passwd_prog'}) { local $out; @@ -1614,6 +1593,40 @@ if ($config{'passwd_mindays'} && $uinfo ne "none") { return undef; } +=head2 is_dictionary_word(word) + +Returns 1 if some file can be found in a dictionary words file + +=cut +sub is_dictionary_word +{ +my ($word) = @_; +$word = lc($word); +my @files; +if ($config{'dict_file'}) { + @files = split(/\s+/, $config{'dict_file'}); + } +else { + @files = ( "/usr/share/dict/words", + "/usr/dict/words" ); + } +foreach my $f (@files) { + my $found = 0; + &open_readfile(WORDS, $f); + while() { + s/#.*//; + s/\s//; + if (lc($_) eq $word) { + $found = 1; + last; + } + } + close(WORDS); + return 1 if ($found); + } +return 0; +} + =head2 check_username_restrictions(username) Returns an error message if a username fails some restriction, or undef if