User-Visible krb5-strength Changes
+krb5-strength 3.1 (unreleased)
+
+ Change the error messages returned for passwords that fail strength
+ checking to start with a capital letter. This appears to be more
+ consistent with the error message conventions used inside Heimdal.
+
krb5-strength 3.0 (2014-03-25)
The krb5-strength plugin and heimdal-strength program now support a
* Checks whether the password satisfies a set of character class rules.
*
* Written by Russ Allbery <eagle@eyrie.org>
- * Copyright 2013
+ * Copyright 2013, 2014
* The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
bool symbol;
};
-/* Abbreviate the most common error reporting syntax. */
-#define MUST_HAVE(ctx, err) \
- strength_error_class((ctx), "password must contain " err)
-
/*
* Analyze a password and fill out a struct with flags indicating which
if (length < rule->min || (rule->max > 0 && length > rule->max))
return 0;
if (rule->lower && !classes->lower)
- return MUST_HAVE(ctx, "a lowercase letter");
+ return strength_error_class((ctx), ERROR_CLASS_LOWER);
if (rule->upper && !classes->upper)
- return MUST_HAVE(ctx, "an uppercase letter");
+ return strength_error_class((ctx), ERROR_CLASS_UPPER);
if (rule->digit && !classes->digit)
- return MUST_HAVE(ctx, "a number");
+ return strength_error_class((ctx), ERROR_CLASS_DIGIT);
if (rule->symbol && !classes->symbol)
- return MUST_HAVE(ctx, "a space or punctuation character");
+ return strength_error_class((ctx), ERROR_CLASS_SYMBOL);
return 0;
}
#endif
/* Error strings returned (and displayed to the user) for various failures. */
-#define ERROR_ASCII "password contains non-ASCII or control characters"
-#define ERROR_DICT "password found in list of common passwords"
-#define ERROR_LETTER "password is only letters and spaces"
-#define ERROR_MINDIFF "password does not contain enough unique characters"
-#define ERROR_SHORT "password is too short"
-#define ERROR_USERNAME "password based on username or principal"
+#define ERROR_ASCII "Password contains non-ASCII or control characters"
+#define ERROR_CLASS_LOWER "Password must contain a lowercase letter"
+#define ERROR_CLASS_UPPER "Password must contain an uppercase letter"
+#define ERROR_CLASS_DIGIT "Password must contain a number"
+#define ERROR_CLASS_SYMBOL \
+ "Password must contain a space or punctuation character"
+#define ERROR_DICT "Password found in list of common passwords"
+#define ERROR_LETTER "Password is only letters and spaces"
+#define ERROR_MINDIFF "Password does not contain enough unique characters"
+#define ERROR_SHORT "Password is too short"
+#define ERROR_USERNAME "Password based on username or principal"
/*
* A character class rule, which consists of a minimum length to which the
"principal": "test@EXAMPLE.ORG",
"password": "password",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (longer)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (drop first)",
"principal": "test@EXAMPLE.ORG",
"password": "1bitterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (drop last)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbane1",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (drop first two)",
"principal": "test@EXAMPLE.ORG",
"password": "abbitterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (drop last two)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbane12",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (drop first and last)",
"principal": "test@EXAMPLE.ORG",
"password": "'bitterbane'",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "dictionary with three characters",
"principal": "test@EXAMPLE.ORG",
"password": "PASSWORD98!",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain a lowercase letter"
+ "error": "Password must contain a lowercase letter"
},
{
"name": "no uppercase (11)",
"principal": "test@EXAMPLE.ORG",
"password": "password98!",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain an uppercase letter"
+ "error": "Password must contain an uppercase letter"
},
{
"name": "no digit (11)",
"principal": "test@EXAMPLE.ORG",
"password": "passwordXX!",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain a number"
+ "error": "Password must contain a number"
},
{
"name": "no symbol (11)",
"principal": "test@EXAMPLE.ORG",
"password": "passwordXX9",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain a space or punctuation character"
+ "error": "Password must contain a space or punctuation character"
},
{
"name": "all classes (11)",
"principal": "test@EXAMPLE.ORG",
"password": "PASSWORD98!WORD",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain a lowercase letter"
+ "error": "Password must contain a lowercase letter"
},
{
"name": "no uppercase (15)",
"principal": "test@EXAMPLE.ORG",
"password": "password98!word",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain an uppercase letter"
+ "error": "Password must contain an uppercase letter"
},
{
"name": "no digit (15)",
"principal": "test@EXAMPLE.ORG",
"password": "passwordXX!word",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain a number"
+ "error": "Password must contain a number"
},
{
"name": "no symbol (12)",
"principal": "test@EXAMPLE.ORG",
"password": "PASSWORD98!WORDWORD",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain a lowercase letter"
+ "error": "Password must contain a lowercase letter"
},
{
"name": "no uppercase (19)",
"principal": "test@EXAMPLE.ORG",
"password": "password98!wordword",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password must contain an uppercase letter"
+ "error": "Password must contain an uppercase letter"
},
{
"name": "no digit (16)",
"name": "repeating the same password",
"principal": "someuser@EXAMPLE.ORG",
"password": "password",
- "error": "password was previously used"
+ "error": "Password was previously used"
},
{
"name": "different password works",
"name": "now that one fails",
"principal": "someuser@EXAMPLE.ORG",
"password": "password2",
- "error": "password was previously used"
+ "error": "Password was previously used"
},
{
"name": "previous password still fails",
"principal": "someuser@EXAMPLE.ORG",
"password": "password",
- "error": "password was previously used"
+ "error": "Password was previously used"
},
{
"name": "succeeds for different user",
"name": "based on principal",
"principal": "someuser@EXAMPLE.ORG",
"password": "someuser",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
}
]
"principal": "test@EXAMPLE.COM",
"password": "vUCZ2aX$Y.e",
"code": "KADM5_PASS_Q_TOOSHORT",
- "error": "password is too short"
+ "error": "Password is too short"
},
{
"name": "sufficiently long password",
"principal": "test@EXAMPLE.ORG",
"password": "عربى",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password contains non-ASCII or control characters"
+ "error": "Password contains non-ASCII or control characters"
},
{
"name": "control character",
"principal": "test@EXAMPLE.ORG",
"password": "ouchD\u0001artetch",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password contains non-ASCII or control characters"
+ "error": "Password contains non-ASCII or control characters"
},
{
"name": "tab",
"principal": "test@EXAMPLE.ORG",
"password": "\touchDartetch",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password contains non-ASCII or control characters"
+ "error": "Password contains non-ASCII or control characters"
},
{
"name": "all alphabetic",
"principal": "test@EXAMPLE.ORG",
"password": "ouchDartetch",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password is only letters and spaces"
+ "error": "Password is only letters and spaces"
},
{
"name": "all alphabetic with spaces",
"principal": "test@EXAMPLE.ORG",
"password": "the perils of all good dogs",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password is only letters and spaces"
+ "error": "Password is only letters and spaces"
},
{
"name": "punctuation",
"principal": "test@EXAMPLE.ORG",
"password": "11111111111111111111",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password does not contain enough unique characters"
+ "error": "Password does not contain enough unique characters"
},
{
"name": "mindiff (2 characters)",
"principal": "test@EXAMPLE.ORG",
"password": "1b1b1b1b1b1b1b1b1b1b",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password does not contain enough unique characters"
+ "error": "Password does not contain enough unique characters"
},
{
"name": "mindiff (3 characters)",
"principal": "test@EXAMPLE.ORG",
"password": "1bc1bc1bc1bc1bc1bc1b",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password does not contain enough unique characters"
+ "error": "Password does not contain enough unique characters"
},
{
"name": "mindiff (4 characters)",
"principal": "test@EXAMPLE.ORG",
"password": "1bcd1bcd1bcd1bcd1bcd",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password does not contain enough unique characters"
+ "error": "Password does not contain enough unique characters"
},
{
"name": "mindiff (5 characters)",
"principal": "test@EXAMPLE.ORG",
"password": "1bcde1bcde1bcde1bcde",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password does not contain enough unique characters"
+ "error": "Password does not contain enough unique characters"
},
{
"name": "mindiff (6 characters)",
"principal": "test@EXAMPLE.ORG",
"password": "1bcdef1bcdef1bcdef1b",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password does not contain enough unique characters"
+ "error": "Password does not contain enough unique characters"
},
{
"name": "mindiff (7 characters)",
"principal": "test@EXAMPLE.ORG",
"password": "1cdbfge1cdbeg1fcdbef",
"code": "KADM5_PASS_Q_CLASS",
- "error": "password does not contain enough unique characters"
+ "error": "Password does not contain enough unique characters"
},
{
"name": "mindiff (8 characters)",
"principal": "someuser@EXAMPLE.ORG",
"password": "someuser",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "based on principal (reversed)",
"principal": "someuser@EXAMPLE.ORG",
"password": "resuemos",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "based on principal with digits",
"principal": "someuser@EXAMPLE.ORG",
"password": "someuser123",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "is full principal",
"principal": "test@EXAMPLE.ORG",
"password": "test@EXAMPLE.ORG",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "principal with leading digits",
"principal": "someuser@EXAMPLE.ORG",
"password": "123someuser",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "principal with leading and trailing digits",
"principal": "someuser@EXAMPLE.ORG",
"password": "1someuser2",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "is realm (lowercase)",
"principal": "someuser@NEWEXAMPLE.ORG",
"password": "newexample",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "is realm (lowercase) with digits",
"principal": "someuser@NEWEXAMPLE.ORG",
"password": "newexample123",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "is realm (lowercase) with leading digits",
"principal": "someuser@NEWEXAMPLE.ORG",
"password": "123newexample",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "is realm reversed",
"principal": "someuser@NEWEXAMPLE.ORG",
"password": "ELPMAXEWEN",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "is second realm with digits",
"principal": "someuser@NEWEXAMPLE.ORG",
"password": "ORG1791520",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
},
{
"name": "is whole realm (mixed case)",
"principal": "someuser@NEWEXAMPLE.ORG",
"password": "NewExample.Org",
"code": "KADM5_PASS_Q_GENERIC",
- "error": "password based on username or principal"
+ "error": "Password based on username or principal"
}
]
"principal": "test@EXAMPLE.ORG",
"password": "password",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (longer)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (drop first)",
"principal": "test@EXAMPLE.ORG",
"password": "1bitterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (drop last)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbane1",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "dictionary with three characters",
"principal": "test@EXAMPLE.ORG",
"password": "ab",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "three-character dictionary word",
"principal": "test@EXAMPLE.ORG",
"password": "one",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "single-character password",
"principal": "test@EXAMPLE.ORG",
"password": "itterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 2)",
"principal": "test@EXAMPLE.ORG",
"password": "btterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 3/4)",
"principal": "test@EXAMPLE.ORG",
"password": "biterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 5)",
"principal": "test@EXAMPLE.ORG",
"password": "bittrbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 6)",
"principal": "test@EXAMPLE.ORG",
"password": "bittebane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 7)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 8)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbne",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 9)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbae",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: delete 10)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterban",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 1)",
"principal": "test@EXAMPLE.ORG",
"password": "Citterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 2)",
"principal": "test@EXAMPLE.ORG",
"password": "b7tterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 3)",
"principal": "test@EXAMPLE.ORG",
"password": "bi#terbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 4)",
"principal": "test@EXAMPLE.ORG",
"password": "bit*erbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 5)",
"principal": "test@EXAMPLE.ORG",
"password": "bittgrbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 6)",
"principal": "test@EXAMPLE.ORG",
"password": "bitte.bane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 7)",
"principal": "test@EXAMPLE.ORG",
"password": "bitter ane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 8)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterb-ne",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 9)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbame",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: modify 10)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbanq",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 2)",
"principal": "test@EXAMPLE.ORG",
"password": "b7itterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 3)",
"principal": "test@EXAMPLE.ORG",
"password": "bi#tterbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 4)",
"principal": "test@EXAMPLE.ORG",
"password": "bit*terbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 4)",
"principal": "test@EXAMPLE.ORG",
"password": "bit*terbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 5)",
"principal": "test@EXAMPLE.ORG",
"password": "bittgerbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 6)",
"principal": "test@EXAMPLE.ORG",
"password": "bitte.rbane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 7)",
"principal": "test@EXAMPLE.ORG",
"password": "bitter bane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 8)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterb-ane",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 9)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbamne",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
},
{
"name": "in dictionary (edit: add 10)",
"principal": "test@EXAMPLE.ORG",
"password": "bitterbanqe",
"code": "KADM5_PASS_Q_DICT",
- "error": "password found in list of common passwords"
+ "error": "Password found in list of common passwords"
}
]
# The message to return to the user if we reject the password because it was
# found in the user's history.
-Readonly my $REJECT_MESSAGE => 'password was previously used';
+Readonly my $REJECT_MESSAGE => 'Password was previously used';
# The path to the external strength checking program to run. This is done
# first before checking history, and if it fails, that failure is returned as