19 #include "validatorpwquality_p.h"
20 #include <pwquality.h>
21 #include <QLoggingCategory>
23 using namespace Cutelyst;
26 ValidatorRule(*new ValidatorPwQualityPrivate(field, threshold, options, userName, oldPassword, messages))
42 pwquality_settings_t *pwq = pwquality_default_settings();
45 bool optionsSet =
false;
47 if (options.
type() == QVariant::Map) {
48 const QVariantMap map = options.
toMap();
50 auto i = map.constBegin();
51 while (i != map.constEnd()) {
56 qCWarning(C_VALIDATOR,
"ValidatorPwQuality: Failed to set pwquality option %s: %s", qUtf8Printable(opt), pwquality_strerror(buf,
sizeof(buf), orv,
nullptr));
62 }
else if (options.
type() == QVariant::String) {
65 if (C_VALIDATOR().isWarningEnabled()) {
67 const int rcrv = pwquality_read_config(pwq, configFile.
toUtf8().
constData(), &auxerror);
70 qCWarning(C_VALIDATOR,
"ValidatorPwQuality: Failed to read configuration file %s: %s", qUtf8Printable(configFile), pwquality_strerror(buf,
sizeof(buf), rcrv, auxerror));
81 if (C_VALIDATOR().isWarningEnabled()) {
83 const int rcrv = pwquality_read_config(pwq,
nullptr, &auxerror);
86 qCWarning(C_VALIDATOR,
"ValidatorPwQuality: Failed to read default configuration file: %s", pwquality_strerror(buf,
sizeof(buf), rcrv, auxerror));
89 pwquality_read_config(pwq,
nullptr,
nullptr);
100 rv = pwquality_check(pwq, pw, opw, u,
nullptr);
102 pwquality_free_settings(pwq);
105 rv = PWQ_ERROR_MEM_ALLOC;
108 rv = PWQ_ERROR_EMPTY_PASSWORD;
119 switch (returnValue) {
120 case PWQ_ERROR_MEM_ALLOC:
121 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a memory allocation error.");
123 case PWQ_ERROR_SAME_PASSWORD:
124 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is the same as the old one.");
126 case PWQ_ERROR_PALINDROME:
127 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is a palindrome.");
129 case PWQ_ERROR_CASE_CHANGES_ONLY:
130 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password differs with case changes only.");
132 case PWQ_ERROR_TOO_SIMILAR:
133 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is too similar to the old one.");
135 case PWQ_ERROR_USER_CHECK:
136 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains the user name in some form.");
138 case PWQ_ERROR_GECOS_CHECK:
139 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains words from the real name of the user in some form.");
141 case PWQ_ERROR_BAD_WORDS:
142 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains forbidden words in some form.");
144 case PWQ_ERROR_MIN_DIGITS:
145 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few digits.");
147 case PWQ_ERROR_MIN_UPPERS:
148 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few uppercase letters.");
150 case PWQ_ERROR_MIN_LOWERS:
151 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few lowercase letters.");
153 case PWQ_ERROR_MIN_OTHERS:
154 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few non-alphanumeric characters.");
156 case PWQ_ERROR_MIN_LENGTH:
157 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is too short.");
159 case PWQ_ERROR_ROTATED:
160 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is just the rotated old one.");
162 case PWQ_ERROR_MIN_CLASSES:
163 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password does not contain enough different character types.");
165 case PWQ_ERROR_MAX_CONSECUTIVE:
166 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too many same characters consecutively.");
168 case PWQ_ERROR_MAX_CLASS_REPEAT:
169 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too many characters of the same type consecutively.");
171 case PWQ_ERROR_MAX_SEQUENCE:
172 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too long a monotonous string.");
174 case PWQ_ERROR_EMPTY_PASSWORD:
175 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"No password supplied.");
178 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because we cannot obtain random numbers from the RNG device.");
180 case PWQ_ERROR_CRACKLIB_CHECK:
181 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password fails the dictionary check.");
183 case PWQ_ERROR_UNKNOWN_SETTING:
184 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of an unknown setting.");
186 case PWQ_ERROR_INTEGER:
187 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a bad integer value in the settings.");
189 case PWQ_ERROR_NON_INT_SETTING:
190 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a settings entry is not of integer type.");
192 case PWQ_ERROR_NON_STR_SETTING:
193 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a settings entry is not of string type.");
195 case PWQ_ERROR_CFGFILE_OPEN:
196 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because opening the configuration file failed.");
198 case PWQ_ERROR_CFGFILE_MALFORMED:
199 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because the configuration file is malformed.");
201 case PWQ_ERROR_FATAL_FAILURE:
202 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a fatal failure.");
206 if (returnValue < 0) {
207 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of an unknown error.");
209 if (returnValue < threshold) {
217 switch (returnValue) {
218 case PWQ_ERROR_MEM_ALLOC:
219 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a memory allocation error.").
arg(label);
221 case PWQ_ERROR_SAME_PASSWORD:
222 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is the same as the old one.").
arg(label);
224 case PWQ_ERROR_PALINDROME:
225 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is a palindrome.").
arg(label);
227 case PWQ_ERROR_CASE_CHANGES_ONLY:
228 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field differs with case changes only.").
arg(label);
230 case PWQ_ERROR_TOO_SIMILAR:
231 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is too similar to the old one.").
arg(label);
233 case PWQ_ERROR_USER_CHECK:
234 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains the user name in some form.").
arg(label);
236 case PWQ_ERROR_GECOS_CHECK:
237 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains words from the real name of the user name in some form.").
arg(label);
239 case PWQ_ERROR_BAD_WORDS:
240 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains forbidden words in some form.").
arg(label);
242 case PWQ_ERROR_MIN_DIGITS:
243 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few digits.").
arg(label);
245 case PWQ_ERROR_MIN_UPPERS:
246 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few uppercase letters.").
arg(label);
248 case PWQ_ERROR_MIN_LOWERS:
249 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few lowercase letters.").
arg(label);
251 case PWQ_ERROR_MIN_OTHERS:
252 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few non-alphanumeric characters.").
arg(label);
254 case PWQ_ERROR_MIN_LENGTH:
255 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is too short.").
arg(label);
257 case PWQ_ERROR_ROTATED:
258 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is just the rotated old one.").
arg(label);
260 case PWQ_ERROR_MIN_CLASSES:
261 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field does not contain enough character types.").
arg(label);
263 case PWQ_ERROR_MAX_CONSECUTIVE:
264 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too many same characters consecutively.").
arg(label);
266 case PWQ_ERROR_MAX_CLASS_REPEAT:
267 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too many characters of the same type consecutively.").
arg(label);
269 case PWQ_ERROR_MAX_SEQUENCE:
270 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains contains too long a monotonous string.").
arg(label);
272 case PWQ_ERROR_EMPTY_PASSWORD:
273 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"No password supplied in the “%1” field.").
arg(label);
276 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because we cannot obtain random numbers from the RNG device.").
arg(label);
278 case PWQ_ERROR_CRACKLIB_CHECK:
279 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field fails the dictionary check.").
arg(label);
281 case PWQ_ERROR_UNKNOWN_SETTING:
282 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of an unknown setting.").
arg(label);
284 case PWQ_ERROR_INTEGER:
285 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a bad integer value in the settings.").
arg(label);
287 case PWQ_ERROR_NON_INT_SETTING:
288 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a settings entry is not of integer type.").
arg(label);
290 case PWQ_ERROR_NON_STR_SETTING:
291 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a settings entry is not of string type.").
arg(label);
293 case PWQ_ERROR_CFGFILE_OPEN:
294 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because opening the configuration file failed.").
arg(label);
296 case PWQ_ERROR_CFGFILE_MALFORMED:
297 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because the configuration file is malformed.").
arg(label);
299 case PWQ_ERROR_FATAL_FAILURE:
300 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a fatal failure.").
arg(label);
304 if (returnValue < 0) {
305 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1” field failed because of an unknown error.").
arg(label);
307 if (returnValue < threshold) {
308 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The quality score of %1 for the password in the “%2” field is below the threshold of %3.").
arg(
QString::number(returnValue), label,
QString::number(threshold));
328 if (d->options.isValid()) {
329 if (d->options.type() == QVariant::Map) {
331 }
else if (d->options.type() == QVariant::String) {
332 const QString optString = d->options.toString();
333 if (c->
stash().contains(optString)) {
334 opts = c->
stash(optString);
341 if (!d->userName.isEmpty()) {
342 un = params.
value(d->userName);
344 un = c->
stash(d->userName).toString();
348 if (!d->oldPassword.isEmpty()) {
349 opw = params.
value(d->oldPassword);
351 opw = c->
stash(d->oldPassword).toString();
354 int rv =
validate(v, opts, opw, un);
355 if (rv < d->threshold) {
357 if (C_VALIDATOR().isDebugEnabled()) {
360 qCDebug(C_VALIDATOR,
"ValidatorPwQuality: Validation failed for field %s at %s::%s: %s", qPrintable(
field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), pwquality_strerror(buf,
sizeof(buf), rv,
nullptr));
362 qCDebug(C_VALIDATOR,
"ValidatorPwQuality: Validation failed for field %s at %s::%s because the quality score %i is below the threshold of %i.", qPrintable(
field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), rv, d->threshold);
366 qCDebug(C_VALIDATOR,
"ValidatorPwQuality: \"%s\" got a quality score of %i", qPrintable(v), rv);
379 const int returnValue = errorData.
toInt();
Validates an input field with libpwquality to check password quality.
QString field() const
Returns the name of the field to validate.
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
Stores custom error messages and the input field label.
static int validate(const QString &value, const QVariant &options=QVariant(), const QString &oldPassword=QString(), const QString &user=QString())
Returns the password quality score for value.
QString number(int n, int base)
QString value(const ParamsMultiMap ¶ms) const
Returns the value of the field from the input params.
int toInt(bool *ok) const
~ValidatorPwQuality() override
Deconstructs the ValidatorPwQuality.
QString validationError(Context *c, const QVariant &errorData=QVariant()) const
Returns a descriptive error message if validation failed.
ValidatorPwQuality(const QString &field, int threshold=30, const QVariant &options=QVariant(), const QString &userName=QString(), const QString &oldPassword=QString(), const ValidatorMessages &messages=ValidatorMessages())
Constructs a new ValidatorPwQuality with the given parameters.
const char * constData() const
QString genericValidationError(Context *c, const QVariant &errorData) const override
Returns a generic error message if validation failed.
Base class for all validator rules.
static QString errorString(Context *c, int returnValue, const QString &label=QString(), int threshold=0)
Returns a human readable string for the return value of ValidatorPwQuality::validate() ...
void setValue(const T &value)
QMap< QString, QVariant > toMap() const
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Contains the result of a single input parameter validation.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
void stash(const QVariantHash &unite)
const T value(const Key &key, const T &defaultValue) const
QByteArray toUtf8() const