6 #include "validatorpwquality_p.h"
8 #include <QLoggingCategory>
13 ValidatorRule(*new ValidatorPwQualityPrivate(field, threshold, options, userName, oldPassword, messages))
27 if (!
value.isEmpty()) {
29 pwquality_settings_t *pwq = pwquality_default_settings();
32 bool optionsSet =
false;
33 if (options.isValid()) {
34 if (options.type() == QVariant::Map) {
35 const QVariantMap map = options.toMap();
37 auto i = map.constBegin();
38 while (i != map.constEnd()) {
39 const QString opt = i.key() + QLatin1Char(
'=') + i.value().toString();
40 const int orv = pwquality_set_option(pwq, opt.toUtf8().constData());
43 qCWarning(C_VALIDATOR,
"ValidatorPwQuality: Failed to set pwquality option %s: %s", qUtf8Printable(opt), pwquality_strerror(buf,
sizeof(buf), orv,
nullptr));
49 }
else if (options.type() == QVariant::String) {
50 const QString configFile = options.toString();
51 if (!configFile.isEmpty()) {
52 if (C_VALIDATOR().isWarningEnabled()) {
54 const int rcrv = pwquality_read_config(pwq, configFile.toUtf8().constData(), &auxerror);
57 qCWarning(C_VALIDATOR,
"ValidatorPwQuality: Failed to read configuration file %s: %s", qUtf8Printable(configFile), pwquality_strerror(buf,
sizeof(buf), rcrv, auxerror));
60 pwquality_read_config(pwq, configFile.toUtf8().constData(),
nullptr);
68 if (C_VALIDATOR().isWarningEnabled()) {
70 const int rcrv = pwquality_read_config(pwq,
nullptr, &auxerror);
73 qCWarning(C_VALIDATOR,
"ValidatorPwQuality: Failed to read default configuration file: %s", pwquality_strerror(buf,
sizeof(buf), rcrv, auxerror));
76 pwquality_read_config(pwq,
nullptr,
nullptr);
80 const QByteArray pwba =
value.toUtf8();
81 const char *pw = pwba.constData();
82 const QByteArray opwba = oldPassword.toUtf8();
83 const char *opw = opwba.isEmpty() ? nullptr : opwba.constData();
84 const QByteArray uba = user.toUtf8();
85 const char *u = uba.isEmpty() ? nullptr : uba.constData();
87 rv = pwquality_check(pwq, pw, opw, u,
nullptr);
89 pwquality_free_settings(pwq);
92 rv = PWQ_ERROR_MEM_ALLOC;
95 rv = PWQ_ERROR_EMPTY_PASSWORD;
105 if (
label.isEmpty()) {
106 switch (returnValue) {
107 case PWQ_ERROR_MEM_ALLOC:
108 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a memory allocation error.");
110 case PWQ_ERROR_SAME_PASSWORD:
111 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is the same as the old one.");
113 case PWQ_ERROR_PALINDROME:
114 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is a palindrome.");
116 case PWQ_ERROR_CASE_CHANGES_ONLY:
117 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password differs with case changes only.");
119 case PWQ_ERROR_TOO_SIMILAR:
120 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is too similar to the old one.");
122 case PWQ_ERROR_USER_CHECK:
123 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains the user name in some form.");
125 case PWQ_ERROR_GECOS_CHECK:
126 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains words from the real name of the user in some form.");
128 case PWQ_ERROR_BAD_WORDS:
129 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains forbidden words in some form.");
131 case PWQ_ERROR_MIN_DIGITS:
132 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few digits.");
134 case PWQ_ERROR_MIN_UPPERS:
135 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few uppercase letters.");
137 case PWQ_ERROR_MIN_LOWERS:
138 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few lowercase letters.");
140 case PWQ_ERROR_MIN_OTHERS:
141 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too few non-alphanumeric characters.");
143 case PWQ_ERROR_MIN_LENGTH:
144 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is too short.");
146 case PWQ_ERROR_ROTATED:
147 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password is just the rotated old one.");
149 case PWQ_ERROR_MIN_CLASSES:
150 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password does not contain enough different character types.");
152 case PWQ_ERROR_MAX_CONSECUTIVE:
153 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too many same characters consecutively.");
155 case PWQ_ERROR_MAX_CLASS_REPEAT:
156 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too many characters of the same type consecutively.");
158 case PWQ_ERROR_MAX_SEQUENCE:
159 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password contains too long a monotonous string.");
161 case PWQ_ERROR_EMPTY_PASSWORD:
162 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"No password supplied.");
165 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because we cannot obtain random numbers from the RNG device.");
167 case PWQ_ERROR_CRACKLIB_CHECK:
168 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password fails the dictionary check.");
170 case PWQ_ERROR_UNKNOWN_SETTING:
171 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of an unknown setting.");
173 case PWQ_ERROR_INTEGER:
174 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a bad integer value in the settings.");
176 case PWQ_ERROR_NON_INT_SETTING:
177 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a settings entry is not of integer type.");
179 case PWQ_ERROR_NON_STR_SETTING:
180 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a settings entry is not of string type.");
182 case PWQ_ERROR_CFGFILE_OPEN:
183 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because opening the configuration file failed.");
185 case PWQ_ERROR_CFGFILE_MALFORMED:
186 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because the configuration file is malformed.");
188 case PWQ_ERROR_FATAL_FAILURE:
189 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of a fatal failure.");
193 if (returnValue < 0) {
194 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check failed because of an unknown error.");
196 if (returnValue < threshold) {
197 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password quality score of %1 is below the threshold of %2.").arg(QString::number(returnValue), QString::number(threshold));
204 switch (returnValue) {
205 case PWQ_ERROR_MEM_ALLOC:
206 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a memory allocation error.").arg(
label);
208 case PWQ_ERROR_SAME_PASSWORD:
209 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is the same as the old one.").arg(
label);
211 case PWQ_ERROR_PALINDROME:
212 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is a palindrome.").arg(
label);
214 case PWQ_ERROR_CASE_CHANGES_ONLY:
215 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field differs with case changes only.").arg(
label);
217 case PWQ_ERROR_TOO_SIMILAR:
218 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is too similar to the old one.").arg(
label);
220 case PWQ_ERROR_USER_CHECK:
221 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains the user name in some form.").arg(
label);
223 case PWQ_ERROR_GECOS_CHECK:
224 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);
226 case PWQ_ERROR_BAD_WORDS:
227 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains forbidden words in some form.").arg(
label);
229 case PWQ_ERROR_MIN_DIGITS:
230 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few digits.").arg(
label);
232 case PWQ_ERROR_MIN_UPPERS:
233 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few uppercase letters.").arg(
label);
235 case PWQ_ERROR_MIN_LOWERS:
236 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few lowercase letters.").arg(
label);
238 case PWQ_ERROR_MIN_OTHERS:
239 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too few non-alphanumeric characters.").arg(
label);
241 case PWQ_ERROR_MIN_LENGTH:
242 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is too short.").arg(
label);
244 case PWQ_ERROR_ROTATED:
245 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field is just the rotated old one.").arg(
label);
247 case PWQ_ERROR_MIN_CLASSES:
248 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field does not contain enough character types.").arg(
label);
250 case PWQ_ERROR_MAX_CONSECUTIVE:
251 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too many same characters consecutively.").arg(
label);
253 case PWQ_ERROR_MAX_CLASS_REPEAT:
254 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains too many characters of the same type consecutively.").arg(
label);
256 case PWQ_ERROR_MAX_SEQUENCE:
257 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field contains contains too long a monotonous string.").arg(
label);
259 case PWQ_ERROR_EMPTY_PASSWORD:
260 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"No password supplied in the “%1” field.").arg(
label);
263 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);
265 case PWQ_ERROR_CRACKLIB_CHECK:
266 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"The password in the “%1” field fails the dictionary check.").arg(
label);
268 case PWQ_ERROR_UNKNOWN_SETTING:
269 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of an unknown setting.").arg(
label);
271 case PWQ_ERROR_INTEGER:
272 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a bad integer value in the settings.").arg(
label);
274 case PWQ_ERROR_NON_INT_SETTING:
275 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);
277 case PWQ_ERROR_NON_STR_SETTING:
278 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);
280 case PWQ_ERROR_CFGFILE_OPEN:
281 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because opening the configuration file failed.").arg(
label);
283 case PWQ_ERROR_CFGFILE_MALFORMED:
284 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because the configuration file is malformed.").arg(
label);
286 case PWQ_ERROR_FATAL_FAILURE:
287 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1“ field failed because of a fatal failure.").arg(
label);
291 if (returnValue < 0) {
292 error = c->
translate(
"Cutelyst::ValidatorPwQuality",
"Password quality check for the “%1” field failed because of an unknown error.").arg(
label);
294 if (returnValue < threshold) {
295 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));
310 const QString v =
value(params);
315 if (d->options.isValid()) {
316 if (d->options.type() == QVariant::Map) {
318 }
else if (d->options.type() == QVariant::String) {
319 const QString optString = d->options.toString();
320 if (c->
stash().contains(optString)) {
321 opts = c->
stash(optString);
328 if (!d->userName.isEmpty()) {
329 un = params.value(d->userName);
331 un = c->
stash(d->userName).toString();
335 if (!d->oldPassword.isEmpty()) {
336 opw = params.value(d->oldPassword);
338 opw = c->
stash(d->oldPassword).toString();
341 int rv =
validate(v, opts, opw, un);
342 if (rv < d->threshold) {
344 if (C_VALIDATOR().isDebugEnabled()) {
347 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));
349 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);
353 qCDebug(C_VALIDATOR,
"ValidatorPwQuality: \"%s\" got a quality score of %i", qPrintable(v), rv);
366 const int returnValue = errorData.toInt();
367 const QString _label =
label(c);
void stash(const QVariantHash &unite)
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Validates an input field with libpwquality to check password quality.
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.
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()
QString genericValidationError(Context *c, const QVariant &errorData) const override
Returns a generic error message if validation failed.
~ValidatorPwQuality() override
Deconstructs the ValidatorPwQuality.
Base class for all validator rules.
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
QString field() const
Returns the name of the field to validate.
QString value(const ParamsMultiMap ¶ms) const
Returns the value of the field from the input params.
QString validationError(Context *c, const QVariant &errorData=QVariant()) const
Returns a descriptive error message if validation failed.
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.
The Cutelyst namespace holds all public Cutelyst API.
QMultiMap< QString, QString > ParamsMultiMap
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.