From: Moritz Bunkus Date: Wed, 19 Jan 2011 10:15:53 +0000 (+0100) Subject: Eine Klasse zur Überprüfung der Passwortrichtlinie X-Git-Tag: release-2.6.3~61^2~7^2~1^2~16 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=03c526b3b946d62f95ce78420552d62b39e03bed;p=kivitendo-erp.git Eine Klasse zur Überprüfung der Passwortrichtlinie Conflicts: locale/de/all --- diff --git a/SL/Auth/PasswordPolicy.pm b/SL/Auth/PasswordPolicy.pm new file mode 100644 index 000000000..866e49c1e --- /dev/null +++ b/SL/Auth/PasswordPolicy.pm @@ -0,0 +1,168 @@ +package SL::Auth::PasswordPolicy; + +use strict; + +use parent qw(Rose::Object); + +use constant OK => 0; +use constant TOO_SHORT => 1; +use constant TOO_LONG => 2; +use constant MISSING_LOWERCASE => 4; +use constant MISSING_UPPERCASE => 8; +use constant MISSING_DIGIT => 16; +use constant MISSING_SPECIAL_CHAR => 32; +use constant INVALID_CHAR => 64; + +use Rose::Object::MakeMethods::Generic +( + 'scalar --get_set_init' => 'config', +); + +sub verify { + my ($self, $password) = @_; + + my $cfg = $self->config; + return OK() unless $cfg && %{ $cfg }; + + my $result = OK(); + $result |= TOO_SHORT() if $cfg->{min_length} && (length($password) < $cfg->{min_length}); + $result |= TOO_LONG() if $cfg->{max_length} && (length($password) > $cfg->{max_length}); + $result |= MISSING_LOWERCASE() if $cfg->{require_lowercase} && $password !~ m/[a-z]/; + $result |= MISSING_UPPERCASE() if $cfg->{require_uppercase} && $password !~ m/[A-Z]/; + $result |= MISSING_DIGIT() if $cfg->{require_digit} && $password !~ m/[0-9]/; + $result |= MISSING_SPECIAL_CHAR() if $cfg->{require_special_character} && $password !~ $cfg->{special_characters_re}; + $result |= INVALID_CHAR() if $cfg->{invalid_characters_re} && $password =~ $cfg->{invalid_characters_re}; + + return $result; +} + +sub errors { + my ($self, $result) = @_; + + my @errors; + + push @errors, $::locale->text('The password is too short (minimum length: #1).', $self->config->{min_length}) if $result & TOO_SHORT(); + push @errors, $::locale->text('The password is too long (maximum length: #1).', $self->config->{max_length}) if $result & TOO_LONG(); + push @errors, $::locale->text('A lower-case character is required.') if $result & MISSING_LOWERCASE(); + push @errors, $::locale->text('An upper-case character is required.') if $result & MISSING_UPPERCASE(); + push @errors, $::locale->text('A digit is required.') if $result & MISSING_DIGIT(); + + if ($result & MISSING_SPECIAL_CHAR()) { + my $char_list = join ' ', sort split(m//, $self->config->{special_characters}); + push @errors, $::locale->text('A special character is required (valid characters: #1).', $char_list); + } + + if (($result & INVALID_CHAR())) { + my $char_list = join ' ', sort split(m//, $self->config->{ $self->config->{invalid_characters} ? 'invalid_characters' : 'valid_characters' }); + push @errors, $::locale->text('An invalid character was used (invalid characters: #1).', $char_list) if $self->config->{invalid_characters}; + push @errors, $::locale->text('An invalid character was used (valid characters: #1).', $char_list) if $self->config->{valid_characters}; + } + + return @errors; +} + + +sub init_config { + my ($self) = @_; + + my %cfg = %{ $::emmvee_conf{password_policy} || {} }; + + $cfg{valid_characters} =~ s/[ \n\r]//g if $cfg{valid_characters}; + $cfg{invalid_characters} =~ s/[ \n\r]//g if $cfg{invalid_characters}; + $cfg{invalid_characters_re} = '[^' . quotemeta($cfg{valid_characters}) . ']' if $cfg{valid_characters}; + $cfg{invalid_characters_re} = '[' . quotemeta($cfg{invalid_characters}) . ']' if $cfg{invalid_characters}; + $cfg{special_characters} = '!@#$%^&*()_+=[]{}<>\'"|\\,;.:?-'; + $cfg{special_characters_re} = '[' . quotemeta($cfg{special_characters}) . ']'; + print $cfg{special_characters_re}, "\n"; + + map { $cfg{"require_${_}"} = $cfg{"require_${_}"} =~ m/^(?:1|true|t|yes|y)$/i } qw(lowercase uppercase digit special_char); + + $self->config(\%cfg); +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Auth::PasswordPolicy - Verify a given password against the policy +set in the configuration file + +=head1 SYNOPSIS + + my $verifier = SL::Auth::PasswordPolicy->new; + my $result = $verifier->verify($password); + if ($result != SL::Auth::PasswordPolicy->OK()) { + print "Errors: " . join(' ', $verifier->errors($result)) . "\n"; + } + +=head1 CONSTANTS + +=over 4 + +=item C + +Password is OK. + +=item C + +The password is too short. + +=item C + +The password is too long. + +=item C + +The password is missing a lower-case character. + +=item C + +The password is missing an upper-case character. + +=item C + +The password is missing a digit. + +=item C + +The password is missing a special character. Special characters are +the following: ! " # $ % & ' ( ) * + , - . : ; E = E ? @ [ \ ] +^ _ { | } + +=item C + +The password contains an invalid character. + +=back + +=head1 FUNCTIONS + +=over 4 + +=item C + +Checks whether or not the password matches the policy. Returns C +if it does and an error code otherwise (binary or'ed of the error +constants). + +=item C + +Returns an array of human-readable strings describing the issues set +in C<$code> which should be the result of L. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/config/lx_office.conf.default b/config/lx_office.conf.default index cd230d223..dd4dffa4f 100644 --- a/config/lx_office.conf.default +++ b/config/lx_office.conf.default @@ -29,6 +29,31 @@ login = demo # location of history file for permanent history history_file = users/console_history +# Settings used when the user changes his/her password. All options +# default to no restriction if unset. +[password_policy] +# Minimum length in number of characters. +min_length = +# Maximum length in number of characters. +max_length = +# Require a lowe-case character? +require_lowercase = +# Require an upper-case character? +require_uppercase = +# Require a digit? +require_digit = +# Require a special char? Special chars are the following: +# ! " # $ % & ' ( ) * + , - . : ; < = > ? @ [ \ ] ^ _ { | } +require_special_character = +# Optional list of valid characters. Spaces are ignored. If set then +# the password must only consist of these characters. +valid_characters = +# Optional list of invalid characters. Spaces are ignored. +invalid_characters = +# Whether or not to check the policy if the password is set from the +# user administration. +disable_policy_for_admin = + [debug] # Use DBIx::Log4perl for logging DBI calls. The string LXDEBUGFILE # will be replaced by the file name configured for $::lxdebug. diff --git a/locale/de/all b/locale/de/all index 115222d37..00d74fdbb 100644 --- a/locale/de/all +++ b/locale/de/all @@ -38,9 +38,12 @@ $self->{texts} = { '4. Quarter' => '4. Quartal', 'What do you want to look for?' => 'Wonach wollen Sie suchen?', 'A Buchungsgruppe consists of a descriptive name and the account numbers for the income and expense accounts for those four tax zones as well as the inventory account number.' => 'Eine Buchungsgruppe besteht aus einem deskriptiven Namen, den Erlös- und Aufwandskonten für diese vier Steuerzonen sowie aus einem Inventarkonto.', + 'A digit is required.' => 'Eine Ziffer ist vorgeschrieben.', 'A group named "Full Access" has been created.' => 'Eine Gruppe namens "Vollzugriff" wurde angelegt.', 'A group with that name does already exist.' => 'Eine Gruppe mit diesem Namen gibt es bereits.', 'A lot of the usability of Lx-Office has been enhanced with javascript. Although it is currently possible to use every aspect of Lx-Office without javascript, we strongly recommend it. In a future version this may change and javascript may be necessary to access advanced features.' => 'Die Bedienung von Lx-Office wurde an vielen Stellen mit Javascript verbessert. Obwohl es derzeit möglich ist, jeden Aspekt von Lx-Office auch ohne Javascript zu benutzen, empfehlen wir es. In einer zukünftigen Version wird Javascript eventuell notwendig sein um weitergehende Features zu benutzen.', + 'A lower-case character is required.' => 'Ein Kleinbuchstabe ist vorgeschrieben.', + 'A special character is required (valid characters: #1).' => 'Ein Sonderzeichen ist vorgeschrieben (gültige Zeichen: #1).', 'A temporary directory could not be created:' => 'Ein temporäres Verzeichnis konnte nicht erstellt werden:', 'A temporary file could not be created. Please verify that the directory "#1" is writeable by the webserver.' => 'Eine temporäre Datei konnte nicht angelegt werden. Bitte stellen Sie sicher, dass das Verzeichnis "#1" vom Webserver beschrieben werden darf.', 'A temporary file could not be created:' => 'Eine temporäre Datei konnte nicht erstellt werden:', @@ -180,6 +183,9 @@ $self->{texts} = { 'Amount' => 'Betrag', 'Amount Due' => 'Betrag fällig', 'Amount has to be greater then zero! Wrong row number: ' => 'Leere Eingabe oder Werte kleiner, gleich null eingegeben. Fehler in Reihe Nummer: ', + 'An invalid character was used (invalid characters: #1).' => 'Ein ungültiges Zeichen wurde benutzt (ungültige Zeichen: #1).', + 'An invalid character was used (valid characters: #1).' => 'Ein ungültiges Zeichen wurde benutzt (gültige Zeichen: #1).', + 'An upper-case character is required.' => 'Ein Großbuchstabe ist vorgeschrieben.', 'Annotations' => 'Anmerkungen', 'Another user with the login #1 does already exist.' => 'Es existiert bereits ein anderer Benutzer mit diesem Login.', 'Ap aging on %s' => 'Offene Verbindlichkeiten zum %s', @@ -815,7 +821,6 @@ $self->{texts} = { 'Help Template Variables' => 'Hilfe zu Dokumenten-Variablen', 'Here\'s an example command line:' => 'Hier ist eine Kommandozeile, die als Beispiel dient:', 'Hide by default' => 'Standardmäßig verstecken', - 'History' => 'Historie', 'History Search' => 'Historien Suche', 'History Search Engine' => 'Historien Suchmaschine', 'Homepage' => 'Homepage', @@ -1679,6 +1684,8 @@ $self->{texts} = { 'The parts have been removed.' => 'Die Waren wurden aus dem Lager entnommen.', 'The parts have been stocked.' => 'Die Artikel wurden eingelagert.', 'The parts have been transferred.' => 'Die Waren wurden umgelagert.', + 'The password is too long (maximum length: #1).' => 'Das Passwort ist zu lang (maximale Länge: #1).', + 'The password is too short (minimum length: #1).' => 'Das Password ist zu kurz (minimale Länge: #1).', 'The payments have been posted.' => 'Die Zahlungen wurden gebucht.', 'The pg_dump process could not be started.' => 'Der pg_dump-Prozess konnte nicht gestartet werden.', 'The pg_restore process could not be started.' => 'Der pg_restore-Prozess konnte nicht gestartet werden.', diff --git a/scripts/locales.pl b/scripts/locales.pl index b972a49db..f03e5c667 100755 --- a/scripts/locales.pl +++ b/scripts/locales.pl @@ -31,7 +31,7 @@ parse_args(); my $basedir = "../.."; my $locales_dir = "."; my $bindir = "$basedir/bin/mozilla"; -my @progdirs = ( "$basedir/SL/Controller", "$basedir/SL/Template/Plugin" ); +my @progdirs = ( "$basedir/SL/Controller", "$basedir/SL/Template/Plugin", "$basedir/SL/Auth" ); my $dbupdir = "$basedir/sql/Pg-upgrade"; my $dbupdir2 = "$basedir/sql/Pg-upgrade2"; my $menufile = "menu.ini";