18 #include "credentialpassword_p.h"
19 #include "authenticationrealm.h"
21 #include <QLoggingCategory>
22 #include <QMessageAuthenticationCode>
28 Q_LOGGING_CATEGORY(C_CREDENTIALPASSWORD,
"cutelyst.plugin.credentialpassword", QtWarningMsg)
31 , d_ptr(new CredentialPasswordPrivate)
36 CredentialPassword::~CredentialPassword()
47 if (d->checkPassword(_user, authinfo)) {
50 qCDebug(C_CREDENTIALPASSWORD) <<
"Password didn't match";
53 qCDebug(C_CREDENTIALPASSWORD) <<
"Unable to locate a user matching user info provided in realm";
61 return d->passwordField;
67 d->passwordField = fieldName;
73 return d->passwordType;
79 d->passwordType = type;
85 return d->passwordPreSalt;
97 return d->passwordPostSalt;
110 for(
int i = 0; i < a.
size() && i < b.
size(); i++) {
116 #define HASH_SECTIONS 4
117 #define HASH_ALGORITHM_INDEX 0
118 #define HASH_ITERATION_INDEX 1
119 #define HASH_SALT_INDEX 2
120 #define HASH_PBKDF2_INDEX 3
124 if (params.
size() < HASH_SECTIONS) {
128 int method = CredentialPasswordPrivate::cryptoStrToEnum(params.
at(HASH_ALGORITHM_INDEX));
139 params.
at(HASH_SALT_INDEX),
140 params.
at(HASH_ITERATION_INDEX).toInt(),
150 QFile random(QStringLiteral(
"/dev/urandom"));
152 salt = random.
read(saltByteSize).toBase64();
160 const QByteArray methodStr = CredentialPasswordPrivate::cryptoEnumToStr(method);
184 if (rounds <= 0 || keyLength <= 0) {
185 qCCritical(C_CREDENTIALPASSWORD,
"PBKDF2 ERROR: Invalid parameters.");
189 if (salt.
size() == 0 || salt.
size() > std::numeric_limits<int>::max() - 4) {
194 int saltSize = salt.
size();
196 asalt.
resize(saltSize + 4);
202 for (
int count = 1, remainingBytes = keyLength; remainingBytes > 0; ++count) {
203 asalt[saltSize + 0] =
static_cast<char>((count >> 24) & 0xff);
204 asalt[saltSize + 1] =
static_cast<char>((count >> 16) & 0xff);
205 asalt[saltSize + 2] =
static_cast<char>((count >> 8) & 0xff);
206 asalt[saltSize + 3] =
static_cast<char>(count & 0xff);
210 obuf = d1 = code.
result();
212 for (
int i = 1; i < rounds; ++i) {
216 auto it = obuf.
begin();
218 while (d1It != d1.
cend()) {
226 remainingBytes -= obuf.
size();
229 key = key.
mid(0, keyLength);
243 if (Q_LIKELY(passwordType == CredentialPassword::Hashed)) {
244 if (!passwordPreSalt.isEmpty()) {
248 if (!passwordPostSalt.isEmpty()) {
249 password.
append(password);
253 }
else if (passwordType == CredentialPassword::Clear) {
254 return storedPassword == password;
255 }
else if (passwordType == CredentialPassword::None) {
256 qCDebug(C_CREDENTIALPASSWORD) <<
"CredentialPassword is set to ignore password check";
267 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
269 hashmethod = QByteArrayLiteral(
"Md4");
271 hashmethod = QByteArrayLiteral(
"Md5");
275 hashmethod = QByteArrayLiteral(
"Sha1");
277 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
279 hashmethod = QByteArrayLiteral(
"Sha224");
281 hashmethod = QByteArrayLiteral(
"Sha256");
283 hashmethod = QByteArrayLiteral(
"Sha384");
285 hashmethod = QByteArrayLiteral(
"Sha512");
287 hashmethod = QByteArrayLiteral(
"Sha3_224");
289 hashmethod = QByteArrayLiteral(
"Sha3_256");
291 hashmethod = QByteArrayLiteral(
"Sha3_384");
293 hashmethod = QByteArrayLiteral(
"Sha3_512");
300 int CredentialPasswordPrivate::cryptoStrToEnum(
const QByteArray &hashMethod)
305 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
306 if (hashmethod ==
"Md4") {
308 }
else if (hashmethod ==
"Md5") {
312 if (hashmethod ==
"Sha1") {
315 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
316 if (hashmethod ==
"Sha224") {
318 }
else if (hashmethod ==
"Sha256") {
320 }
else if (hashmethod ==
"Sha384") {
322 }
else if (hashmethod ==
"Sha512") {
324 }
else if (hashmethod ==
"Sha3_224") {
326 }
else if (hashmethod ==
"Sha3_256") {
328 }
else if (hashmethod ==
"Sha3_384") {
330 }
else if (hashmethod ==
"Sha3_512") {
338 #include "moc_credentialpassword.cpp"
QByteArray result() const const
QString passwordField() const
Returns the field to look for when authenticating the user.
QString passwordPostSalt() const
Returns the salt string to be appended to the password.
QByteArray hash(const QByteArray &message, const QByteArray &key, QCryptographicHash::Algorithm method)
QByteArray & append(char ch)
virtual bool open(QIODevice::OpenMode mode) override
const T value(const Key &key, const T &defaultValue) const const
bool isNull() const
Returns true if the object is null.
QString & prepend(QChar ch)
QByteArray number(int n, int base)
QList< QByteArray > split(char sep) const const
void setPasswordField(const QString &fieldName)
Sets the field to look for when authenticating the user.
PasswordType passwordType() const
Returns the type of password this class will be dealing with.
QByteArray toBase64(QByteArray::Base64Options options) const const
QByteArray toRfc4122() const const
QByteArray::iterator begin()
QString passwordPreSalt() const
Returns the salt string to be prepended to the password.
static bool validatePassword(const QByteArray &password, const QByteArray &correctHash)
Validates the given password against the correct hash.
QByteArray::const_iterator cend() const const
QByteArray mid(int pos, int len) const const
QByteArray toUtf8() const const
const T & at(int i) const const
void addData(const char *data, int length)
QByteArray fromBase64(const QByteArray &base64, QByteArray::Base64Options options)
static QByteArray createPassword(const QByteArray &password, QCryptographicHash::Algorithm method, int iterations, int saltByteSize, int hashByteSize)
Creates a password hash string.
qint64 read(char *data, qint64 maxSize)
The Cutelyst namespace holds all public Cutelyst API.
void setPasswordPreSalt(const QString &passwordPreSalt)
Sets the salt string to be prepended to the password.
QByteArray::const_iterator cbegin() const const
void setPasswordType(PasswordType type)
Sets the type of password this class will be dealing with.
virtual AuthenticationUser findUser(Context *c, const ParamsMultiMap &userinfo)
Tries to find the user with authinfo returning a non null AuthenticationUser on success.
AuthenticationUser authenticate(Context *c, AuthenticationRealm *realm, const ParamsMultiMap &authinfo) final
Tries to authenticate the authinfo using the give realm.
static QByteArray pbkdf2(QCryptographicHash::Algorithm method, const QByteArray &password, const QByteArray &salt, int rounds, int keyLength)
Generates a pbkdf2 string for the given password.
void setPasswordPostSalt(const QString &passwordPostSalt)
Sets the salt string to be appended to the password.
QString & append(QChar ch)
static QByteArray hmac(QCryptographicHash::Algorithm method, const QByteArray &key, const QByteArray &message)
Generates the Hash-based message authentication code.
QString toString() const const