diff options
Diffstat (limited to 'src/network/kernel/qauthenticator.cpp')
-rw-r--r-- | src/network/kernel/qauthenticator.cpp | 63 |
1 files changed, 34 insertions, 29 deletions
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 9e5f48c456..e42450d7e5 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -14,6 +14,7 @@ #include <qstring.h> #include <qdatetime.h> #include <qrandom.h> +#include <QtNetwork/qhttpheaders.h> #ifdef Q_OS_WIN #include <qmutex.h> @@ -444,13 +445,14 @@ static bool verifyDigestMD5(QByteArrayView value) return true; // assume it's ok if algorithm is not specified } -void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByteArray>> &values, +void QAuthenticatorPrivate::parseHttpResponse(const QHttpHeaders &headers, bool isProxy, QStringView host) { #if !QT_CONFIG(gssapi) Q_UNUSED(host); #endif - const char *search = isProxy ? "proxy-authenticate" : "www-authenticate"; + const auto search = isProxy ? QHttpHeaders::WellKnownHeader::ProxyAuthenticate + : QHttpHeaders::WellKnownHeader::WWWAuthenticate; method = None; /* @@ -463,26 +465,23 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt authentication parameters. */ - QByteArray headerVal; - for (int i = 0; i < values.size(); ++i) { - const QPair<QByteArray, QByteArray> ¤t = values.at(i); - if (current.first.compare(search, Qt::CaseInsensitive) != 0) - continue; - QByteArray str = current.second.toLower(); - if (method < Basic && str.startsWith("basic")) { + QByteArrayView headerVal; + for (const auto ¤t : headers.values(search)) { + const QLatin1StringView str(current); + if (method < Basic && str.startsWith("basic"_L1, Qt::CaseInsensitive)) { method = Basic; - headerVal = current.second.mid(6); - } else if (method < Ntlm && str.startsWith("ntlm")) { + headerVal = QByteArrayView(current).mid(6); + } else if (method < Ntlm && str.startsWith("ntlm"_L1, Qt::CaseInsensitive)) { method = Ntlm; - headerVal = current.second.mid(5); - } else if (method < DigestMd5 && str.startsWith("digest")) { + headerVal = QByteArrayView(current).mid(5); + } else if (method < DigestMd5 && str.startsWith("digest"_L1, Qt::CaseInsensitive)) { // Make sure the algorithm is actually MD5 before committing to it: - if (!verifyDigestMD5(QByteArrayView(current.second).sliced(7))) + if (!verifyDigestMD5(QByteArrayView(current).sliced(7))) continue; method = DigestMd5; - headerVal = current.second.mid(7); - } else if (method < Negotiate && str.startsWith("negotiate")) { + headerVal = QByteArrayView(current).mid(7); + } else if (method < Negotiate && str.startsWith("negotiate"_L1, Qt::CaseInsensitive)) { #if QT_CONFIG(sspi) || QT_CONFIG(gssapi) // if it's not supported then we shouldn't try to use it #if QT_CONFIG(gssapi) // For GSSAPI there needs to be a KDC set up for the host (afaict). @@ -492,14 +491,14 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt continue; #endif method = Negotiate; - headerVal = current.second.mid(10); + headerVal = QByteArrayView(current).mid(10); #endif } } // Reparse credentials since we know the method now updateCredentials(); - challenge = headerVal.trimmed(); + challenge = headerVal.trimmed().toByteArray(); QHash<QByteArray, QByteArray> options = parseDigestAuthenticationChallenge(challenge); // Sets phase to Start if this updates our realm and sets the two locations where we store @@ -547,16 +546,14 @@ QByteArray QAuthenticatorPrivate::calculateResponse(QByteArrayView requestMethod Q_UNUSED(host); #endif QByteArray response; - const char* methodString = nullptr; + QByteArrayView methodString; switch(method) { case QAuthenticatorPrivate::None: - methodString = ""; phase = Done; break; case QAuthenticatorPrivate::Basic: methodString = "Basic"; - response = user.toLatin1() + ':' + password.toLatin1(); - response = response.toBase64(); + response = (user + ':'_L1 + password).toLatin1().toBase64(); phase = Done; break; case QAuthenticatorPrivate::DigestMd5: @@ -645,26 +642,35 @@ QByteArray QAuthenticatorPrivate::calculateResponse(QByteArrayView requestMethod break; } - return QByteArray::fromRawData(methodString, qstrlen(methodString)) + ' ' + response; + return methodString + ' ' + response; } // ---------------------------- Digest Md5 code ---------------------------------------- +static bool containsAuth(QByteArrayView data) +{ + for (auto element : QLatin1StringView(data).tokenize(','_L1)) { + if (element == "auth"_L1) + return true; + } + return false; +} + QHash<QByteArray, QByteArray> QAuthenticatorPrivate::parseDigestAuthenticationChallenge(QByteArrayView challenge) { QHash<QByteArray, QByteArray> options; // parse the challenge const char *d = challenge.data(); - const char *end = d + challenge.length(); + const char *end = d + challenge.size(); while (d < end) { while (d < end && (*d == ' ' || *d == '\n' || *d == '\r')) ++d; const char *start = d; while (d < end && *d != '=') ++d; - QByteArray key = QByteArray(start, d - start); + QByteArrayView key = QByteArrayView(start, d - start); ++d; if (d >= end) break; @@ -695,13 +701,12 @@ QAuthenticatorPrivate::parseDigestAuthenticationChallenge(QByteArrayView challen while (d < end && *d != ',') ++d; ++d; - options[key] = value; + options[key.toByteArray()] = std::move(value); } QByteArray qop = options.value("qop"); if (!qop.isEmpty()) { - QList<QByteArray> qopoptions = qop.split(','); - if (!qopoptions.contains("auth")) + if (!containsAuth(qop)) return QHash<QByteArray, QByteArray>(); // #### can't do auth-int currently // if (qop.contains("auth-int")) @@ -1759,7 +1764,7 @@ static QByteArray qGssapiContinue(QAuthenticatorPrivate *ctx, QByteArrayView cha if (!challenge.isEmpty()) { inBuf.value = const_cast<char*>(challenge.data()); - inBuf.length = challenge.length(); + inBuf.length = challenge.size(); } majStat = gss_init_sec_context(&minStat, |