19 #include "validatorpwquality_p.h"
20 #include <pwquality.h>
21 #include <QLoggingCategory>
26 ValidatorRule(*new ValidatorPwQualityPrivate(field, threshold, options, userName, oldPassword, messages))
40 if (!
value.isEmpty()) {
42 pwquality_settings_t *pwq = pwquality_default_settings();
45 bool optionsSet =
false;
46 if (options.isValid()) {
47 if (options.type() == QVariant::Map) {
48 const QVariantMap map = options.toMap();
50 auto i = map.constBegin();
51 while (i != map.constEnd()) {
52 const QString opt = i.key() + QLatin1Char(
'=') + i.value().toString();
53 const int orv = pwquality_set_option(pwq, opt.toUtf8().constData());
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) {
63 const QString configFile = options.toString();
64 if (!configFile.isEmpty()) {
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));
73 pwquality_read_config(pwq, configFile.toUtf8().constData(),
nullptr);
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);
93 const QByteArray pwba =
value.toUtf8();
94 const char *pw = pwba.constData();
95 const QByteArray opwba = oldPassword.toUtf8();
96 const char *opw = opwba.isEmpty() ? nullptr : opwba.constData();
97 const QByteArray uba = user.toUtf8();
98 const char *u = uba.isEmpty() ? nullptr : uba.constData();
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;
118 if (
label.isEmpty()) {
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) {
210 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password quality score of %1 is below the threshold of %2.").arg(QString::number(returnValue), QString::number(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));
323 const QString v =
value(params);
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);
367 result.
value.setValue<QString>(v);
379 const int returnValue = errorData.toInt();
380 const QString _label =
label(c);