Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qnetworkaccessauthenticationmanager.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#
include
"qnetworkaccessauthenticationmanager_p.h"
6
#
include
"qnetworkaccessmanager.h"
7
#
include
"qnetworkaccessmanager_p.h"
8
9
#
include
"QtCore/qbuffer.h"
10
#
include
"QtCore/qlist.h"
11
#
include
"QtCore/qurl.h"
12
#
include
"QtCore/QMutexLocker"
13
#
include
"QtNetwork/qauthenticator.h"
14
15
#
include
<
algorithm
>
16
17
QT_BEGIN_NAMESPACE
18
19
using
namespace
Qt::StringLiterals;
20
21
class
QNetworkAuthenticationCache
:
private
QList
<
QNetworkAuthenticationCredential
>,
22
public
QNetworkAccessCache
::
CacheableObject
23
{
24
public
:
25
QNetworkAuthenticationCache
()
26
:
CacheableObject
(
Option
::
Shareable
)
27
{
28
reserve(1);
29
}
30
31
using
QList
<
QNetworkAuthenticationCredential
>::
begin
;
32
using
QList
<
QNetworkAuthenticationCredential
>::
end
;
33
34
iterator
findClosestMatch
(
const
QString &domain)
35
{
36
iterator it =
std
::lower_bound(begin(), end(), domain);
37
if
(it == end() && !isEmpty())
38
--it;
39
if
(it == end() || !domain.startsWith(it->domain))
40
return
end();
41
return
it;
42
}
43
44
void
insert
(
const
QString &domain,
const
QString &user,
const
QString &password)
45
{
46
iterator closestMatch = findClosestMatch(domain);
47
if
(closestMatch != end() && closestMatch->domain == domain) {
48
// we're overriding the current credentials
49
closestMatch->user = user;
50
closestMatch->password = password;
51
}
else
{
52
QNetworkAuthenticationCredential
newCredential;
53
newCredential.domain = domain;
54
newCredential.user = user;
55
newCredential.password = password;
56
57
if
(closestMatch != end())
58
QList<QNetworkAuthenticationCredential>::insert(++closestMatch, newCredential);
59
else
60
QList<QNetworkAuthenticationCredential>::insert(end(), newCredential);
61
}
62
}
63
64
virtual
void
dispose
()
override
{
delete
this
; }
65
};
66
67
#
ifndef
QT_NO_NETWORKPROXY
68
static
QByteArray
proxyAuthenticationKey
(
const
QNetworkProxy &proxy,
const
QString &realm)
69
{
70
QUrl key;
71
72
switch
(proxy.type()) {
73
case
QNetworkProxy::Socks5Proxy:
74
key.setScheme(
"proxy-socks5"_L1
);
75
break
;
76
77
case
QNetworkProxy::HttpProxy:
78
case
QNetworkProxy::HttpCachingProxy:
79
key.setScheme(
"proxy-http"_L1
);
80
break
;
81
82
case
QNetworkProxy::FtpCachingProxy:
83
key.setScheme(
"proxy-ftp"_L1
);
84
break
;
85
86
case
QNetworkProxy::DefaultProxy:
87
case
QNetworkProxy::NoProxy:
88
// shouldn't happen
89
return
QByteArray();
90
91
// no default:
92
// let there be errors if a new proxy type is added in the future
93
}
94
95
if
(key.scheme().isEmpty())
96
// proxy type not handled
97
return
QByteArray();
98
99
key.setUserName(proxy.user());
100
key.setHost(proxy.hostName());
101
key.setPort(proxy.port());
102
key.setFragment(realm);
103
return
"auth:"
+ key.toEncoded();
104
}
105
#
endif
106
107
static
inline
QByteArray
authenticationKey
(
const
QUrl &url,
const
QString &realm)
108
{
109
QUrl copy = url;
110
copy.setFragment(realm);
111
return
"auth:"
+ copy.toEncoded(QUrl::RemovePassword | QUrl::RemovePath | QUrl::RemoveQuery);
112
}
113
114
115
#
ifndef
QT_NO_NETWORKPROXY
116
void
QNetworkAccessAuthenticationManager
::
cacheProxyCredentials
(
const
QNetworkProxy &p,
117
const
QAuthenticator *authenticator)
118
{
119
Q_ASSERT(authenticator);
120
Q_ASSERT(p.type() != QNetworkProxy::DefaultProxy);
121
Q_ASSERT(p.type() != QNetworkProxy::NoProxy);
122
123
QMutexLocker mutexLocker(&mutex);
124
125
QString realm = authenticator->realm();
126
QNetworkProxy proxy = p;
127
proxy.setUser(authenticator->user());
128
129
// don't cache null passwords, empty password may be valid though
130
if
(authenticator->password().isNull())
131
return
;
132
133
// Set two credentials: one with the username and one without
134
do
{
135
// Set two credentials actually: one with and one without the realm
136
do
{
137
QByteArray
cacheKey = proxyAuthenticationKey(proxy, realm);
138
if
(cacheKey.isEmpty())
139
return
;
// should not happen
140
141
QNetworkAuthenticationCache
*auth =
new
QNetworkAuthenticationCache
;
142
auth->insert(QString(), authenticator->user(), authenticator->password());
143
authenticationCache.addEntry(cacheKey, auth);
// replace the existing one, if there's any
144
145
if
(realm.isEmpty()) {
146
break
;
147
}
else
{
148
realm.clear();
149
}
150
}
while
(
true
);
151
152
if
(proxy.user().isEmpty())
153
break
;
154
else
155
proxy.setUser(QString());
156
}
while
(
true
);
157
}
158
159
QNetworkAuthenticationCredential
160
QNetworkAccessAuthenticationManager
::
fetchCachedProxyCredentials
(
const
QNetworkProxy &p,
161
const
QAuthenticator *authenticator)
162
{
163
QNetworkProxy proxy = p;
164
if
(proxy.type() == QNetworkProxy::DefaultProxy) {
165
proxy = QNetworkProxy::applicationProxy();
166
}
167
if
(!proxy.password().isEmpty())
168
return
QNetworkAuthenticationCredential
();
// no need to set credentials if it already has them
169
170
QString realm;
171
if
(authenticator)
172
realm = authenticator->realm();
173
174
QMutexLocker mutexLocker(&mutex);
175
QByteArray
cacheKey = proxyAuthenticationKey(proxy, realm);
176
if
(cacheKey.isEmpty())
177
return
QNetworkAuthenticationCredential
();
178
if
(!authenticationCache.hasEntry(cacheKey))
179
return
QNetworkAuthenticationCredential
();
180
181
QNetworkAuthenticationCache
*auth =
182
static_cast
<QNetworkAuthenticationCache *>(authenticationCache.requestEntryNow(cacheKey));
183
QNetworkAuthenticationCredential
cred = *auth->findClosestMatch(QString());
184
authenticationCache.releaseEntry(cacheKey);
185
186
// proxy cache credentials always have exactly one item
187
Q_ASSERT_X(!cred
.
isNull
(
)
,
"QNetworkAccessManager"
,
188
"Internal inconsistency: found a cache key for a proxy, but it's empty"
);
189
return
cred;
190
}
191
192
#
endif
193
194
void
QNetworkAccessAuthenticationManager
::
cacheCredentials
(
const
QUrl &url,
195
const
QAuthenticator *authenticator)
196
{
197
Q_ASSERT(authenticator);
198
if
(authenticator->isNull())
199
return
;
200
QString domain = QString::fromLatin1(
"/"
);
// FIXME: make QAuthenticator return the domain
201
QString realm = authenticator->realm();
202
203
QMutexLocker mutexLocker(&mutex);
204
205
// Set two credentials actually: one with and one without the username in the URL
206
QUrl copy = url;
207
copy.setUserName(authenticator->user());
208
do
{
209
QByteArray
cacheKey = authenticationKey(copy, realm);
210
if
(authenticationCache.hasEntry(cacheKey)) {
211
QNetworkAuthenticationCache
*auth =
212
static_cast
<QNetworkAuthenticationCache *>(authenticationCache.requestEntryNow(cacheKey));
213
auth->insert(domain, authenticator->user(), authenticator->password());
214
authenticationCache.releaseEntry(cacheKey);
215
}
else
{
216
QNetworkAuthenticationCache
*auth =
new
QNetworkAuthenticationCache
;
217
auth->insert(domain, authenticator->user(), authenticator->password());
218
authenticationCache.addEntry(cacheKey, auth);
219
}
220
221
if
(copy.userName().isEmpty()) {
222
break
;
223
}
else
{
224
copy.setUserName(QString());
225
}
226
}
while
(
true
);
227
}
228
229
/*!
230
\class QNetworkAccessAuthenticationManager
231
\internal
232
*/
233
234
/*!
235
Fetch the credential data from the credential cache.
236
237
If auth is 0 (as it is when called from createRequest()), this will try to
238
look up with an empty realm. That fails in most cases for HTTP (because the
239
realm is seldom empty for HTTP challenges). In any case, QHttpNetworkConnection
240
never sends the credentials on the first attempt: it needs to find out what
241
authentication methods the server supports.
242
243
For FTP, realm is always empty.
244
*/
245
QNetworkAuthenticationCredential
246
QNetworkAccessAuthenticationManager
::
fetchCachedCredentials
(
const
QUrl &url,
247
const
QAuthenticator *authentication)
248
{
249
if
(!url.password().isEmpty())
250
return
QNetworkAuthenticationCredential
();
// no need to set credentials if it already has them
251
252
QString realm;
253
if
(authentication)
254
realm = authentication->realm();
255
256
QByteArray
cacheKey = authenticationKey(url, realm);
257
258
QMutexLocker mutexLocker(&mutex);
259
if
(!authenticationCache.hasEntry(cacheKey))
260
return
QNetworkAuthenticationCredential
();
261
262
QNetworkAuthenticationCache
*auth =
263
static_cast
<QNetworkAuthenticationCache *>(authenticationCache.requestEntryNow(cacheKey));
264
auto
cred = auth->findClosestMatch(url.path());
265
QNetworkAuthenticationCredential
ret;
266
if
(cred != auth->end())
267
ret = *cred;
268
authenticationCache.releaseEntry(cacheKey);
269
return
ret;
270
}
271
272
void
QNetworkAccessAuthenticationManager
::
clearCache
()
273
{
274
authenticationCache.clear();
275
}
276
277
QT_END_NAMESPACE
QByteArray::FromBase64Result
\inmodule QtCore
Definition
qbytearray.h:824
QNetworkAccessAuthenticationManager
Definition
qnetworkaccessauthenticationmanager_p.h:51
QNetworkAccessAuthenticationManager::cacheCredentials
void cacheCredentials(const QUrl &url, const QAuthenticator *auth)
Definition
qnetworkaccessauthenticationmanager.cpp:194
QNetworkAccessAuthenticationManager::clearCache
void clearCache()
Definition
qnetworkaccessauthenticationmanager.cpp:272
QNetworkAccessAuthenticationManager::fetchCachedCredentials
QNetworkAuthenticationCredential fetchCachedCredentials(const QUrl &url, const QAuthenticator *auth=nullptr)
Fetch the credential data from the credential cache.
Definition
qnetworkaccessauthenticationmanager.cpp:246
QNetworkAccessAuthenticationManager::fetchCachedProxyCredentials
QNetworkAuthenticationCredential fetchCachedProxyCredentials(const QNetworkProxy &proxy, const QAuthenticator *auth=nullptr)
Definition
qnetworkaccessauthenticationmanager.cpp:160
QNetworkAccessAuthenticationManager::cacheProxyCredentials
void cacheProxyCredentials(const QNetworkProxy &proxy, const QAuthenticator *auth)
Definition
qnetworkaccessauthenticationmanager.cpp:116
QNetworkAccessCache::CacheableObject
Definition
qnetworkaccesscache_p.h:44
QNetworkAccessCache::CacheableObject::Option
Option
Definition
qnetworkaccesscache_p.h:51
QNetworkAccessCache::CacheableObject::Option::Shareable
@ Shareable
Definition
qnetworkaccesscache_p.h:53
QNetworkAccessCache
Definition
qnetworkaccesscache_p.h:38
QNetworkAuthenticationCache
Definition
qnetworkaccessauthenticationmanager.cpp:23
QNetworkAuthenticationCache::findClosestMatch
iterator findClosestMatch(const QString &domain)
Definition
qnetworkaccessauthenticationmanager.cpp:34
QNetworkAuthenticationCache::insert
void insert(const QString &domain, const QString &user, const QString &password)
Definition
qnetworkaccessauthenticationmanager.cpp:44
QNetworkAuthenticationCache::dispose
virtual void dispose() override
Definition
qnetworkaccessauthenticationmanager.cpp:64
QNetworkAuthenticationCache::QNetworkAuthenticationCache
QNetworkAuthenticationCache()
Definition
qnetworkaccessauthenticationmanager.cpp:25
QNetworkAuthenticationCredential
Definition
qnetworkaccessauthenticationmanager_p.h:33
QNetworkAuthenticationCredential::isNull
bool isNull() const
Definition
qnetworkaccessauthenticationmanager_p.h:38
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
proxyAuthenticationKey
static QByteArray proxyAuthenticationKey(const QNetworkProxy &proxy, const QString &realm)
Definition
qnetworkaccessauthenticationmanager.cpp:68
authenticationKey
static QByteArray authenticationKey(const QUrl &url, const QString &realm)
Definition
qnetworkaccessauthenticationmanager.cpp:107
qtbase
src
network
access
qnetworkaccessauthenticationmanager.cpp
Generated on
for Qt by
1.18.0