From 07558eaffd34a90576077beb721ef1c010634dda Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Wed, 23 Jul 2014 19:09:14 -0400 Subject: [PATCH] Adds rule that password not appear in a blacklist --- .gitignore | 3 +- README.md | 8 +++-- lib/PasswordPolicy/Policy.php | 9 +++++ lib/PasswordPolicy/Rules/Base.php | 3 ++ lib/PasswordPolicy/Rules/Blacklist.php | 50 ++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 lib/PasswordPolicy/Rules/Blacklist.php diff --git a/.gitignore b/.gitignore index 5657f6e..06ecb66 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -vendor \ No newline at end of file +/vendor +/.* \ No newline at end of file diff --git a/README.md b/README.md index 0592d8f..3137163 100644 --- a/README.md +++ b/README.md @@ -49,23 +49,25 @@ Then, add rules: * `match($regex, $description)`: Checks if the password matches the regex. + * `notInBlacklist($path, $isCaseSensitive = true, $description = null)`: Checks if the password exists in a blacklist. + ### Supported Constraints: The policy also has short-cut helpers for creating constraints: * `atLeast($n)`: At least the param matches - Equivilant to `between($n, PHP_INT_MAX)` + Equivalent to `between($n, PHP_INT_MAX)` * `atMost($n)`: At most the param matches - Equivilant to `between(0, $n)` + Equivalent to `between(0, $n)` * `between($min, $max)`: Between $min and $max number of matches * `never()`: No matches - Equivilant to `between(0, 0)` + Equivalent to `between(0, 0)` ## Testing the policy diff --git a/lib/PasswordPolicy/Policy.php b/lib/PasswordPolicy/Policy.php index 78fda6e..931c1a5 100644 --- a/lib/PasswordPolicy/Policy.php +++ b/lib/PasswordPolicy/Policy.php @@ -4,6 +4,9 @@ class Policy { + /** + * @var Rule[] + */ protected $rules = array(); public function atLeast($n) { @@ -81,6 +84,12 @@ public function match($regex, $description) { return $this; } + public function notInBlacklist($path, $isCaseSensitive = true, $description = null) { + $rule = new Rules\Blacklist($path, $isCaseSensitive, $description); + $this->rules[] = $rule; + return $this; + } + public function addRule(Rule $rule) { $this->rules[] = $rule; } diff --git a/lib/PasswordPolicy/Rules/Base.php b/lib/PasswordPolicy/Rules/Base.php index d43e98a..c415802 100644 --- a/lib/PasswordPolicy/Rules/Base.php +++ b/lib/PasswordPolicy/Rules/Base.php @@ -4,6 +4,9 @@ abstract class Base implements \PasswordPolicy\Rule { + /** + * @var \PasswordPolicy\Constraint + */ protected $constraint = null; public function getMessage() { diff --git a/lib/PasswordPolicy/Rules/Blacklist.php b/lib/PasswordPolicy/Rules/Blacklist.php new file mode 100644 index 0000000..1b00d30 --- /dev/null +++ b/lib/PasswordPolicy/Rules/Blacklist.php @@ -0,0 +1,50 @@ +path = $path; + $this->isCaseSensitive = (bool) $isCaseSensitive; + $this->description = $description; + } + + public function getMessage() { + return $this->description; + } + + public function setConstraint(\PasswordPolicy\Constraint $constraint) { + // unused + } + + public function test($password) { + $options = "-m 1"; // stop at first match + if (!$this->isCaseSensitive) { + $options .= " -i"; + } + $command = "fgrep $options " . escapeshellarg($password) . " " . escapeshellarg($this->path); + $result = shell_exec($command); + return (trim($result) === ''); + } + + public function toJavaScript() { + return '{ + message: "Blacklists not implemented client-side", + check: function(p) { return true; } + }'; + } + +} \ No newline at end of file