kernel/qauthenticator.cpp

Switch to Source codePreprocessed file
LineSource CodeCoverage
1 -
2 -
3 -
4 -
5 -
6 -
7static QByteArray qNtlmPhase1(); -
8static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data); -
9QAuthenticator::QAuthenticator() -
10 : d(0) -
11{ -
12}
executed: }
Execution Count:6158
6158
13 -
14 -
15 -
16 -
17QAuthenticator::~QAuthenticator() -
18{ -
19 if (d)
evaluated: d
TRUEFALSE
yes
Evaluation Count:1698
yes
Evaluation Count:4460
1698-4460
20 delete d;
executed: delete d;
Execution Count:1698
1698
21}
executed: }
Execution Count:6158
6158
22 -
23 -
24 -
25 -
26QAuthenticator::QAuthenticator(const QAuthenticator &other) -
27 : d(0) -
28{ -
29 if (other.d)
never evaluated: other.d
0
30 *this = other;
never executed: *this = other;
0
31}
never executed: }
0
32 -
33 -
34 -
35 -
36QAuthenticator &QAuthenticator::operator=(const QAuthenticator &other) -
37{ -
38 if (d == other.d)
partially evaluated: d == other.d
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:33
0-33
39 return *this;
never executed: return *this;
0
40 -
41 -
42 -
43 -
44 detach(); -
45 if (other.d) {
partially evaluated: other.d
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:33
0-33
46 d->user = other.d->user; -
47 d->userDomain = other.d->userDomain; -
48 d->workstation = other.d->workstation; -
49 d->extractedUser = other.d->extractedUser; -
50 d->password = other.d->password; -
51 d->realm = other.d->realm; -
52 d->method = other.d->method; -
53 d->options = other.d->options; -
54 } else {
never executed: }
0
55 delete d; -
56 d = 0; -
57 }
executed: }
Execution Count:33
33
58 return *this;
executed: return *this;
Execution Count:33
33
59} -
60 -
61 -
62 -
63 -
64 -
65bool QAuthenticator::operator==(const QAuthenticator &other) const -
66{ -
67 if (d == other.d)
never evaluated: d == other.d
0
68 return true;
never executed: return true;
0
69 return d->user == other.d->user 0
70 && d->password == other.d->password 0
71 && d->realm == other.d->realm 0
72 && d->method == other.d->method 0
73 && d->options == other.d->options;
never executed: return d->user == other.d->user && d->password == other.d->password && d->realm == other.d->realm && d->method == other.d->method && d->options == other.d->options;
0
74} -
75QString QAuthenticator::user() const -
76{ -
77 return d ? d->user : QString();
executed: return d ? d->user : QString();
Execution Count:3588
3588
78} -
79 -
80 -
81 -
82 -
83 -
84 -
85void QAuthenticator::setUser(const QString &user) -
86{ -
87 detach(); -
88 d->user = user; -
89 d->updateCredentials(); -
90}
executed: }
Execution Count:879
879
91 -
92 -
93 -
94 -
95QString QAuthenticator::password() const -
96{ -
97 return d ? d->password : QString();
executed: return d ? d->password : QString();
Execution Count:3295
3295
98} -
99 -
100 -
101 -
102 -
103 -
104 -
105void QAuthenticator::setPassword(const QString &password) -
106{ -
107 detach(); -
108 d->password = password; -
109}
executed: }
Execution Count:889
889
110 -
111 -
112 -
113 -
114void QAuthenticator::detach() -
115{ -
116 if (!d) {
evaluated: !d
TRUEFALSE
yes
Evaluation Count:1731
yes
Evaluation Count:1451
1451-1731
117 d = new QAuthenticatorPrivate; -
118 return;
executed: return;
Execution Count:1731
1731
119 } -
120 -
121 d->phase = QAuthenticatorPrivate::Start; -
122}
executed: }
Execution Count:1451
1451
123 -
124 -
125 -
126 -
127QString QAuthenticator::realm() const -
128{ -
129 return d ? d->realm : QString();
executed: return d ? d->realm : QString();
Execution Count:406
406
130} -
131QVariant QAuthenticator::option(const QString &opt) const -
132{ -
133 return d ? d->options.value(opt) : QVariant();
never executed: return d ? d->options.value(opt) : QVariant();
0
134} -
135QVariantHash QAuthenticator::options() const -
136{ -
137 return d ? d->options : QVariantHash();
never executed: return d ? d->options : QVariantHash();
0
138} -
139void QAuthenticator::setOption(const QString &opt, const QVariant &value) -
140{ -
141 detach(); -
142 d->options.insert(opt, value); -
143}
never executed: }
0
144 -
145 -
146 -
147 -
148 -
149bool QAuthenticator::isNull() const -
150{ -
151 return !d;
executed: return !d;
Execution Count:349
349
152} -
153QAuthenticatorPrivate::QAuthenticatorPrivate() -
154 : method(None) -
155 -
156 -
157 -
158 , hasFailed(false) -
159 , phase(Start) -
160 , nonceCount(0) -
161{ -
162 cnonce = QCryptographicHash::hash(QByteArray::number(qrand(), 16) + QByteArray::number(qrand(), 16), -
163 QCryptographicHash::Md5).toHex(); -
164 nonceCount = 0; -
165}
executed: }
Execution Count:1731
1731
166 -
167QAuthenticatorPrivate::~QAuthenticatorPrivate() -
168{ -
169 -
170 -
171 -
172 -
173} -
174 -
175void QAuthenticatorPrivate::updateCredentials() -
176{ -
177 int separatorPosn = 0; -
178 -
179 switch (method) { -
180 case QAuthenticatorPrivate::Ntlm: -
181 if ((separatorPosn = user.indexOf(QLatin1String("\\"))) != -1) {
never evaluated: (separatorPosn = user.indexOf(QLatin1String("\\"))) != -1
0
182 -
183 realm.clear(); -
184 userDomain = user.left(separatorPosn); -
185 extractedUser = user.mid(separatorPosn + 1); -
186 } else {
never executed: }
0
187 extractedUser = user; -
188 realm.clear(); -
189 userDomain.clear(); -
190 }
never executed: }
0
191 break;
never executed: break;
0
192 default: -
193 userDomain.clear(); -
194 break;
executed: break;
Execution Count:1221
1221
195 } -
196}
executed: }
Execution Count:1221
1221
197 -
198void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByteArray> > &values, bool isProxy) -
199{ -
200 const char *search = isProxy ? "proxy-authenticate" : "www-authenticate";
evaluated: isProxy
TRUEFALSE
yes
Evaluation Count:67
yes
Evaluation Count:275
67-275
201 -
202 method = None; -
203 QByteArray headerVal; -
204 for (int i = 0; i < values.size(); ++i) {
evaluated: i < values.size()
TRUEFALSE
yes
Evaluation Count:2727
yes
Evaluation Count:342
342-2727
205 const QPair<QByteArray, QByteArray> &current = values.at(i); -
206 if (current.first.toLower() != search)
evaluated: current.first.toLower() != search
TRUEFALSE
yes
Evaluation Count:2385
yes
Evaluation Count:342
342-2385
207 continue;
executed: continue;
Execution Count:2385
2385
208 QByteArray str = current.second.toLower(); -
209 if (method < Basic && str.startsWith("basic")) {
partially evaluated: method < Basic
TRUEFALSE
yes
Evaluation Count:342
no
Evaluation Count:0
evaluated: str.startsWith("basic")
TRUEFALSE
yes
Evaluation Count:280
yes
Evaluation Count:62
0-342
210 method = Basic; -
211 headerVal = current.second.mid(6); -
212 } else if (method < Ntlm && str.startsWith("ntlm")) {
partially evaluated: method < Ntlm
TRUEFALSE
yes
Evaluation Count:62
no
Evaluation Count:0
partially evaluated: str.startsWith("ntlm")
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:62
executed: }
Execution Count:280
0-280
213 method = Ntlm; -
214 headerVal = current.second.mid(5); -
215 } else if (method < DigestMd5 && str.startsWith("digest")) {
partially evaluated: method < DigestMd5
TRUEFALSE
yes
Evaluation Count:62
no
Evaluation Count:0
partially evaluated: str.startsWith("digest")
TRUEFALSE
yes
Evaluation Count:62
no
Evaluation Count:0
never executed: }
0-62
216 method = DigestMd5; -
217 headerVal = current.second.mid(7); -
218 }
executed: }
Execution Count:62
62
219 } -
220 -
221 -
222 updateCredentials(); -
223 challenge = headerVal.trimmed(); -
224 QHash<QByteArray, QByteArray> options = parseDigestAuthenticationChallenge(challenge); -
225 -
226 switch(method) { -
227 case Basic: -
228 this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); -
229 if (user.isEmpty() && password.isEmpty())
evaluated: user.isEmpty()
TRUEFALSE
yes
Evaluation Count:119
yes
Evaluation Count:161
partially evaluated: password.isEmpty()
TRUEFALSE
yes
Evaluation Count:119
no
Evaluation Count:0
0-161
230 phase = Done;
executed: phase = Done;
Execution Count:119
119
231 break;
executed: break;
Execution Count:280
280
232 case Ntlm: -
233 -
234 if (user.isEmpty() && password.isEmpty())
never evaluated: user.isEmpty()
never evaluated: password.isEmpty()
0
235 phase = Done;
never executed: phase = Done;
0
236 break;
never executed: break;
0
237 case DigestMd5: { -
238 this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); -
239 if (options.value("stale").toLower() == "true")
partially evaluated: options.value("stale").toLower() == "true"
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:62
0-62
240 phase = Start;
never executed: phase = Start;
0
241 if (user.isEmpty() && password.isEmpty())
evaluated: user.isEmpty()
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:56
partially evaluated: password.isEmpty()
TRUEFALSE
yes
Evaluation Count:6
no
Evaluation Count:0
0-56
242 phase = Done;
executed: phase = Done;
Execution Count:6
6
243 break;
executed: break;
Execution Count:62
62
244 } -
245 default: -
246 realm.clear(); -
247 challenge = QByteArray(); -
248 phase = Invalid; -
249 }
never executed: }
0
250}
executed: }
Execution Count:342
342
251 -
252QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMethod, const QByteArray &path) -
253{ -
254 QByteArray response; -
255 const char *methodString = 0; -
256 switch(method) { -
257 case QAuthenticatorPrivate::None: -
258 methodString = ""; -
259 phase = Done; -
260 break;
never executed: break;
0
261 case QAuthenticatorPrivate::Plain: -
262 response = '\0' + user.toUtf8() + '\0' + password.toUtf8(); -
263 phase = Done; -
264 break;
never executed: break;
0
265 case QAuthenticatorPrivate::Basic: -
266 methodString = "Basic "; -
267 response = user.toLatin1() + ':' + password.toLatin1(); -
268 response = response.toBase64(); -
269 phase = Done; -
270 break;
executed: break;
Execution Count:157
157
271 case QAuthenticatorPrivate::Login: -
272 if (challenge.contains("VXNlciBOYW1lAA==")) {
never evaluated: challenge.contains("VXNlciBOYW1lAA==")
0
273 response = user.toUtf8().toBase64(); -
274 phase = Phase2; -
275 } else if (challenge.contains("UGFzc3dvcmQA")) {
never evaluated: challenge.contains("UGFzc3dvcmQA")
never executed: }
0
276 response = password.toUtf8().toBase64(); -
277 phase = Done; -
278 }
never executed: }
0
279 break;
never executed: break;
0
280 case QAuthenticatorPrivate::CramMd5: -
281 break;
never executed: break;
0
282 case QAuthenticatorPrivate::DigestMd5: -
283 methodString = "Digest "; -
284 response = digestMd5Response(challenge, requestMethod, path); -
285 phase = Done; -
286 break;
executed: break;
Execution Count:33
33
287 case QAuthenticatorPrivate::Ntlm: -
288 methodString = "NTLM "; -
289 if (challenge.isEmpty()) {
never evaluated: challenge.isEmpty()
0
290 { -
291 response = qNtlmPhase1().toBase64(); -
292 if (user.isEmpty())
never evaluated: user.isEmpty()
0
293 phase = Done;
never executed: phase = Done;
0
294 else -
295 phase = Phase2;
never executed: phase = Phase2;
0
296 } -
297 } else { -
298 { -
299 response = qNtlmPhase3(this, QByteArray::fromBase64(challenge)).toBase64(); -
300 phase = Done; -
301 } -
302 }
never executed: }
0
303 -
304 break;
never executed: break;
0
305 } -
306 return QByteArray(methodString) + response;
executed: return QByteArray(methodString) + response;
Execution Count:190
190
307} -
308 -
309 -
310 -
311 -
312QHash<QByteArray, QByteArray> QAuthenticatorPrivate::parseDigestAuthenticationChallenge(const QByteArray &challenge) -
313{ -
314 QHash<QByteArray, QByteArray> options; -
315 -
316 const char *d = challenge.constData(); -
317 const char *end = d + challenge.length(); -
318 while (d < end) {
evaluated: d < end
TRUEFALSE
yes
Evaluation Count:660
yes
Evaluation Count:375
375-660
319 while (d < end && (*d == ' ' || *d == '\n' || *d == '\r'))
partially evaluated: d < end
TRUEFALSE
yes
Evaluation Count:945
no
Evaluation Count:0
evaluated: *d == ' '
TRUEFALSE
yes
Evaluation Count:285
yes
Evaluation Count:660
partially evaluated: *d == '\n'
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:660
partially evaluated: *d == '\r'
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:660
0-945
320 ++d;
executed: ++d;
Execution Count:285
285
321 const char *start = d; -
322 while (d < end && *d != '=')
partially evaluated: d < end
TRUEFALSE
yes
Evaluation Count:4150
no
Evaluation Count:0
evaluated: *d != '='
TRUEFALSE
yes
Evaluation Count:3490
yes
Evaluation Count:660
0-4150
323 ++d;
executed: ++d;
Execution Count:3490
3490
324 QByteArray key = QByteArray(start, d - start); -
325 ++d; -
326 if (d >= end)
partially evaluated: d >= end
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:660
0-660
327 break;
never executed: break;
0
328 bool quote = (*d == '"'); -
329 if (quote)
evaluated: quote
TRUEFALSE
yes
Evaluation Count:565
yes
Evaluation Count:95
95-565
330 ++d;
executed: ++d;
Execution Count:565
565
331 if (d >= end)
partially evaluated: d >= end
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:660
0-660
332 break;
never executed: break;
0
333 start = d; -
334 QByteArray value; -
335 while (d < end) {
partially evaluated: d < end
TRUEFALSE
yes
Evaluation Count:13583
no
Evaluation Count:0
0-13583
336 bool backslash = false; -
337 if (*d == '\\' && d < end - 1) {
partially evaluated: *d == '\\'
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:13583
never evaluated: d < end - 1
0-13583
338 ++d; -
339 backslash = true; -
340 }
never executed: }
0
341 if (!backslash) {
partially evaluated: !backslash
TRUEFALSE
yes
Evaluation Count:13583
no
Evaluation Count:0
0-13583
342 if (quote) {
evaluated: quote
TRUEFALSE
yes
Evaluation Count:13203
yes
Evaluation Count:380
380-13203
343 if (*d == '"')
evaluated: *d == '"'
TRUEFALSE
yes
Evaluation Count:565
yes
Evaluation Count:12638
565-12638
344 break;
executed: break;
Execution Count:565
565
345 } else {
executed: }
Execution Count:12638
12638
346 if (*d == ',')
evaluated: *d == ','
TRUEFALSE
yes
Evaluation Count:95
yes
Evaluation Count:285
95-285
347 break;
executed: break;
Execution Count:95
95
348 }
executed: }
Execution Count:285
285
349 } -
350 value += *d; -
351 ++d; -
352 }
executed: }
Execution Count:12923
12923
353 while (d < end && *d != ',')
evaluated: d < end
TRUEFALSE
yes
Evaluation Count:850
yes
Evaluation Count:375
evaluated: *d != ','
TRUEFALSE
yes
Evaluation Count:565
yes
Evaluation Count:285
285-850
354 ++d;
executed: ++d;
Execution Count:565
565
355 ++d; -
356 options[key] = value; -
357 }
executed: }
Execution Count:660
660
358 -
359 QByteArray qop = options.value("qop"); -
360 if (!qop.isEmpty()) {
evaluated: !qop.isEmpty()
TRUEFALSE
yes
Evaluation Count:95
yes
Evaluation Count:280
95-280
361 QList<QByteArray> qopoptions = qop.split(','); -
362 if (!qopoptions.contains("auth"))
partially evaluated: !qopoptions.contains("auth")
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:95
0-95
363 return QHash<QByteArray, QByteArray>();
never executed: return QHash<QByteArray, QByteArray>();
0
364 -
365 -
366 -
367 -
368 -
369 -
370 -
371 options["qop"] = "auth"; -
372 }
executed: }
Execution Count:95
95
373 -
374 return options;
executed: return options;
Execution Count:375
375
375} -
376static QByteArray digestMd5ResponseHelper( -
377 const QByteArray &alg, -
378 const QByteArray &userName, -
379 const QByteArray &realm, -
380 const QByteArray &password, -
381 const QByteArray &nonce, -
382 const QByteArray &nonceCount, -
383 const QByteArray &cNonce, -
384 const QByteArray &qop, -
385 const QByteArray &method, -
386 const QByteArray &digestUri, -
387 const QByteArray &hEntity -
388 ) -
389{ -
390 QCryptographicHash hash(QCryptographicHash::Md5); -
391 hash.addData(userName); -
392 hash.addData(":", 1); -
393 hash.addData(realm); -
394 hash.addData(":", 1); -
395 hash.addData(password); -
396 QByteArray ha1 = hash.result(); -
397 if (alg.toLower() == "md5-sess") {
partially evaluated: alg.toLower() == "md5-sess"
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:33
0-33
398 hash.reset(); -
399 -
400 -
401 -
402 -
403 hash.addData(ha1.toHex()); -
404 hash.addData(":", 1); -
405 hash.addData(nonce); -
406 hash.addData(":", 1); -
407 hash.addData(cNonce); -
408 ha1 = hash.result(); -
409 };
never executed: }
0
410 ha1 = ha1.toHex(); -
411 -
412 -
413 hash.reset(); -
414 hash.addData(method); -
415 hash.addData(":", 1); -
416 hash.addData(digestUri); -
417 if (qop.toLower() == "auth-int") {
partially evaluated: qop.toLower() == "auth-int"
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:33
0-33
418 hash.addData(":", 1); -
419 hash.addData(hEntity); -
420 }
never executed: }
0
421 QByteArray ha2hex = hash.result().toHex(); -
422 -
423 -
424 hash.reset(); -
425 hash.addData(ha1); -
426 hash.addData(":", 1); -
427 hash.addData(nonce); -
428 hash.addData(":", 1); -
429 if (!qop.isNull()) {
partially evaluated: !qop.isNull()
TRUEFALSE
yes
Evaluation Count:33
no
Evaluation Count:0
0-33
430 hash.addData(nonceCount); -
431 hash.addData(":", 1); -
432 hash.addData(cNonce); -
433 hash.addData(":", 1); -
434 hash.addData(qop); -
435 hash.addData(":", 1); -
436 }
executed: }
Execution Count:33
33
437 hash.addData(ha2hex); -
438 return hash.result().toHex();
executed: return hash.result().toHex();
Execution Count:33
33
439} -
440 -
441QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge, const QByteArray &method, const QByteArray &path) -
442{ -
443 QHash<QByteArray,QByteArray> options = parseDigestAuthenticationChallenge(challenge); -
444 -
445 ++nonceCount; -
446 QByteArray nonceCountString = QByteArray::number(nonceCount, 16); -
447 while (nonceCountString.length() < 8)
evaluated: nonceCountString.length() < 8
TRUEFALSE
yes
Evaluation Count:231
yes
Evaluation Count:33
33-231
448 nonceCountString.prepend('0');
executed: nonceCountString.prepend('0');
Execution Count:231
231
449 -
450 QByteArray nonce = options.value("nonce"); -
451 QByteArray opaque = options.value("opaque"); -
452 QByteArray qop = options.value("qop"); -
453 -
454 -
455 QByteArray response = digestMd5ResponseHelper(options.value("algorithm"), user.toLatin1(), -
456 realm.toLatin1(), password.toLatin1(), -
457 nonce, nonceCountString, -
458 cnonce, qop, method, -
459 path, QByteArray()); -
460 -
461 -
462 QByteArray credentials; -
463 credentials += "username=\"" + user.toLatin1() + "\", "; -
464 credentials += "realm=\"" + realm.toLatin1() + "\", "; -
465 credentials += "nonce=\"" + nonce + "\", "; -
466 credentials += "uri=\"" + path + "\", "; -
467 if (!opaque.isEmpty())
partially evaluated: !opaque.isEmpty()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:33
0-33
468 credentials += "opaque=\"" + opaque + "\", ";
never executed: credentials += "opaque=\"" + opaque + "\", ";
0
469 credentials += "response=\"" + response + '\"'; -
470 if (!options.value("algorithm").isEmpty())
partially evaluated: !options.value("algorithm").isEmpty()
TRUEFALSE
yes
Evaluation Count:33
no
Evaluation Count:0
0-33
471 credentials += ", algorithm=" + options.value("algorithm");
executed: credentials += ", algorithm=" + options.value("algorithm");
Execution Count:33
33
472 if (!options.value("qop").isEmpty()) {
partially evaluated: !options.value("qop").isEmpty()
TRUEFALSE
yes
Evaluation Count:33
no
Evaluation Count:0
0-33
473 credentials += ", qop=" + qop + ", "; -
474 credentials += "nc=" + nonceCountString + ", "; -
475 credentials += "cnonce=\"" + cnonce + '\"'; -
476 }
executed: }
Execution Count:33
33
477 -
478 return credentials;
executed: return credentials;
Execution Count:33
33
479} -
480const int blockSize = 64; -
481const int nDigestLen = 16; -
482const quint8 respversion = 1; -
483const quint8 hirespversion = 1; -
484class QNtlmBuffer { -
485public: -
486 QNtlmBuffer() : len(0), maxLen(0), offset(0) {}
never executed: }
0
487 quint16 len; -
488 quint16 maxLen; -
489 quint32 offset; -
490 enum { Size = 8 }; -
491}; -
492 -
493class QNtlmPhase1BlockBase -
494{ -
495public: -
496 char magic[8]; -
497 quint32 type; -
498 quint32 flags; -
499 QNtlmBuffer domain; -
500 QNtlmBuffer workstation; -
501 enum { Size = 32 }; -
502}; -
503 -
504 -
505class QNtlmPhase2BlockBase -
506{ -
507public: -
508 char magic[8]; -
509 quint32 type; -
510 QNtlmBuffer targetName; -
511 quint32 flags; -
512 unsigned char challenge[8]; -
513 quint32 context[2]; -
514 QNtlmBuffer targetInfo; -
515 enum { Size = 48 }; -
516}; -
517 -
518class QNtlmPhase3BlockBase { -
519public: -
520 char magic[8]; -
521 quint32 type; -
522 QNtlmBuffer lmResponse; -
523 QNtlmBuffer ntlmResponse; -
524 QNtlmBuffer domain; -
525 QNtlmBuffer user; -
526 QNtlmBuffer workstation; -
527 QNtlmBuffer sessionKey; -
528 quint32 flags; -
529 enum { Size = 64 }; -
530}; -
531 -
532static void qStreamNtlmBuffer(QDataStream& ds, const QByteArray& s) -
533{ -
534 ds.writeRawData(s.constData(), s.size()); -
535}
never executed: }
0
536 -
537 -
538static void qStreamNtlmString(QDataStream& ds, const QString& s, bool unicode) -
539{ -
540 if (!unicode) {
never evaluated: !unicode
0
541 qStreamNtlmBuffer(ds, s.toLatin1()); -
542 return;
never executed: return;
0
543 } -
544 const ushort *d = s.utf16(); -
545 for (int i = 0; i < s.length(); ++i)
never evaluated: i < s.length()
0
546 ds << d[i];
never executed: ds << d[i];
0
547}
never executed: }
0
548 -
549 -
550 -
551static int qEncodeNtlmBuffer(QNtlmBuffer& buf, int offset, const QByteArray& s) -
552{ -
553 buf.len = s.size(); -
554 buf.maxLen = buf.len; -
555 buf.offset = (offset + 1) & ~1; -
556 return buf.offset + buf.len;
never executed: return buf.offset + buf.len;
0
557} -
558 -
559 -
560static int qEncodeNtlmString(QNtlmBuffer& buf, int offset, const QString& s, bool unicode) -
561{ -
562 if (!unicode)
never evaluated: !unicode
0
563 return qEncodeNtlmBuffer(buf, offset, s.toLatin1());
never executed: return qEncodeNtlmBuffer(buf, offset, s.toLatin1());
0
564 buf.len = 2 * s.length(); -
565 buf.maxLen = buf.len; -
566 buf.offset = (offset + 1) & ~1; -
567 return buf.offset + buf.len;
never executed: return buf.offset + buf.len;
0
568} -
569 -
570 -
571static QDataStream& operator<<(QDataStream& s, const QNtlmBuffer& b) -
572{ -
573 s << b.len << b.maxLen << b.offset; -
574 return s;
never executed: return s;
0
575} -
576 -
577static QDataStream& operator>>(QDataStream& s, QNtlmBuffer& b) -
578{ -
579 s >> b.len >> b.maxLen >> b.offset; -
580 return s;
never executed: return s;
0
581} -
582 -
583 -
584class QNtlmPhase1Block : public QNtlmPhase1BlockBase -
585{ -
586public: -
587 QNtlmPhase1Block() { -
588 qstrncpy(magic, "NTLMSSP", 8); -
589 type = 1; -
590 flags = 0x00000001 | 0x00000200 | 0x00000004; -
591 }
never executed: }
0
592 -
593 -
594 QString domainStr, workstationStr; -
595}; -
596 -
597 -
598class QNtlmPhase2Block : public QNtlmPhase2BlockBase -
599{ -
600public: -
601 QNtlmPhase2Block() { -
602 magic[0] = 0; -
603 type = 0xffffffff; -
604 }
never executed: }
0
605 -
606 -
607 QString targetNameStr, targetInfoStr; -
608 QByteArray targetInfoBuff; -
609}; -
610 -
611 -
612 -
613class QNtlmPhase3Block : public QNtlmPhase3BlockBase { -
614public: -
615 QNtlmPhase3Block() { -
616 qstrncpy(magic, "NTLMSSP", 8); -
617 type = 3; -
618 flags = 0x00000001 | 0x00000200 | 0x00800000; -
619 }
never executed: }
0
620 -
621 -
622 QByteArray lmResponseBuf, ntlmResponseBuf; -
623 QString domainStr, userStr, workstationStr, sessionKeyStr; -
624 QByteArray v2Hash; -
625}; -
626 -
627 -
628static QDataStream& operator<<(QDataStream& s, const QNtlmPhase1Block& b) { -
629 bool unicode = (b.flags & 0x00000001); -
630 -
631 s.writeRawData(b.magic, sizeof(b.magic)); -
632 s << b.type; -
633 s << b.flags; -
634 s << b.domain; -
635 s << b.workstation; -
636 if (!b.domainStr.isEmpty())
never evaluated: !b.domainStr.isEmpty()
0
637 qStreamNtlmString(s, b.domainStr, unicode);
never executed: qStreamNtlmString(s, b.domainStr, unicode);
0
638 if (!b.workstationStr.isEmpty())
never evaluated: !b.workstationStr.isEmpty()
0
639 qStreamNtlmString(s, b.workstationStr, unicode);
never executed: qStreamNtlmString(s, b.workstationStr, unicode);
0
640 return s;
never executed: return s;
0
641} -
642 -
643 -
644static QDataStream& operator<<(QDataStream& s, const QNtlmPhase3Block& b) { -
645 bool unicode = (b.flags & 0x00000001); -
646 s.writeRawData(b.magic, sizeof(b.magic)); -
647 s << b.type; -
648 s << b.lmResponse; -
649 s << b.ntlmResponse; -
650 s << b.domain; -
651 s << b.user; -
652 s << b.workstation; -
653 s << b.sessionKey; -
654 s << b.flags; -
655 -
656 if (!b.domainStr.isEmpty())
never evaluated: !b.domainStr.isEmpty()
0
657 qStreamNtlmString(s, b.domainStr, unicode);
never executed: qStreamNtlmString(s, b.domainStr, unicode);
0
658 -
659 qStreamNtlmString(s, b.userStr, unicode); -
660 -
661 if (!b.workstationStr.isEmpty())
never evaluated: !b.workstationStr.isEmpty()
0
662 qStreamNtlmString(s, b.workstationStr, unicode);
never executed: qStreamNtlmString(s, b.workstationStr, unicode);
0
663 -
664 -
665 qStreamNtlmBuffer(s, b.lmResponseBuf); -
666 qStreamNtlmBuffer(s, b.ntlmResponseBuf); -
667 -
668 -
669 return s;
never executed: return s;
0
670} -
671 -
672 -
673static QByteArray qNtlmPhase1() -
674{ -
675 QByteArray rc; -
676 QDataStream ds(&rc, QIODevice::WriteOnly); -
677 ds.setByteOrder(QDataStream::LittleEndian); -
678 QNtlmPhase1Block pb; -
679 ds << pb; -
680 return rc;
never executed: return rc;
0
681} -
682 -
683 -
684static QByteArray qStringAsUcs2Le(const QString& src) -
685{ -
686 QByteArray rc(2*src.length(), 0); -
687 const unsigned short *s = src.utf16(); -
688 unsigned short *d = (unsigned short*)rc.data(); -
689 for (int i = 0; i < src.length(); ++i) {
never evaluated: i < src.length()
0
690 d[i] = qToLittleEndian(s[i]); -
691 }
never executed: }
0
692 return rc;
never executed: return rc;
0
693} -
694 -
695 -
696static QString qStringFromUcs2Le(const QByteArray& src) -
697{ -
698 qt_noop(); -
699 unsigned short *d = (unsigned short*)src.data(); -
700 for (int i = 0; i < src.length() / 2; ++i) {
never evaluated: i < src.length() / 2
0
701 d[i] = qFromLittleEndian(d[i]); -
702 }
never executed: }
0
703 return QString((const QChar *)src.data(), src.size()/2);
never executed: return QString((const QChar *)src.data(), src.size()/2);
0
704} -
705QByteArray qEncodeHmacMd5(QByteArray &key, const QByteArray &message) -
706{ -
707 qt_noop(); -
708 qt_noop(); -
709 -
710 QCryptographicHash hash(QCryptographicHash::Md5); -
711 QByteArray hMsg; -
712 -
713 QByteArray iKeyPad(blockSize, 0x36); -
714 QByteArray oKeyPad(blockSize, 0x5c); -
715 -
716 hash.reset(); -
717 -
718 -
719 if(blockSize < key.length()) {
never evaluated: blockSize < key.length()
0
720 hash.addData(key); -
721 key = hash.result(); -
722 }
never executed: }
0
723 -
724 -
725 -
726 key = key.leftJustified(blockSize,0,true); -
727 -
728 -
729 -
730 -
731 for(int i = 0; i<key.size();i++) {
never evaluated: i<key.size()
0
732 iKeyPad[i] = key[i]^iKeyPad[i]; -
733 }
never executed: }
0
734 -
735 -
736 for(int i = 0; i<key.size();i++) {
never evaluated: i<key.size()
0
737 oKeyPad[i] = key[i]^oKeyPad[i]; -
738 }
never executed: }
0
739 -
740 iKeyPad.append(message); -
741 -
742 hash.reset(); -
743 hash.addData(iKeyPad); -
744 hMsg = hash.result(); -
745 -
746 -
747 QByteArray hmacDigest; -
748 oKeyPad.append(hMsg); -
749 hash.reset(); -
750 hash.addData(oKeyPad); -
751 hmacDigest = hash.result(); -
752 return hmacDigest;
never executed: return hmacDigest;
0
753} -
754 -
755static QByteArray qCreatev2Hash(const QAuthenticatorPrivate *ctx, -
756 QNtlmPhase3Block *phase3) -
757{ -
758 qt_noop(); -
759 -
760 -
761 if(phase3->v2Hash.size() == 0) {
never evaluated: phase3->v2Hash.size() == 0
0
762 QCryptographicHash md4(QCryptographicHash::Md4); -
763 QByteArray passUnicode = qStringAsUcs2Le(ctx->password); -
764 md4.addData(passUnicode.data(), passUnicode.size()); -
765 -
766 QByteArray hashKey = md4.result(); -
767 qt_noop(); -
768 -
769 QByteArray message = -
770 qStringAsUcs2Le(ctx->extractedUser.toUpper()) + -
771 qStringAsUcs2Le(phase3->domainStr); -
772 -
773 phase3->v2Hash = qEncodeHmacMd5(hashKey, message); -
774 }
never executed: }
0
775 return phase3->v2Hash;
never executed: return phase3->v2Hash;
0
776} -
777 -
778static QByteArray clientChallenge(const QAuthenticatorPrivate *ctx) -
779{ -
780 qt_noop(); -
781 QByteArray clientCh = ctx->cnonce.right(8); -
782 return clientCh;
never executed: return clientCh;
0
783} -
784 -
785 -
786static QByteArray qExtractServerTime(const QByteArray& targetInfoBuff) -
787{ -
788 QByteArray timeArray; -
789 QDataStream ds(targetInfoBuff); -
790 ds.setByteOrder(QDataStream::LittleEndian); -
791 -
792 quint16 avId; -
793 quint16 avLen; -
794 -
795 ds >> avId; -
796 ds >> avLen; -
797 while(avId != 0) {
never evaluated: avId != 0
0
798 if(avId == 7) {
never evaluated: avId == 7
0
799 timeArray.resize(avLen); -
800 -
801 ds.readRawData(timeArray.data(), avLen); -
802 break;
never executed: break;
0
803 } -
804 ds.skipRawData(avLen); -
805 ds >> avId; -
806 ds >> avLen; -
807 }
never executed: }
0
808 return timeArray;
never executed: return timeArray;
0
809} -
810 -
811static QByteArray qEncodeNtlmv2Response(const QAuthenticatorPrivate *ctx, -
812 const QNtlmPhase2Block& ch, -
813 QNtlmPhase3Block *phase3) -
814{ -
815 qt_noop(); -
816 -
817 qCreatev2Hash(ctx, phase3); -
818 -
819 QByteArray temp; -
820 QDataStream ds(&temp, QIODevice::WriteOnly); -
821 ds.setByteOrder(QDataStream::LittleEndian); -
822 -
823 ds << respversion; -
824 ds << hirespversion; -
825 -
826 -
827 QByteArray reserved1(6, 0); -
828 ds.writeRawData(reserved1.constData(), reserved1.size()); -
829 -
830 quint64 time = 0; -
831 QByteArray timeArray; -
832 -
833 if(ch.targetInfo.len)
never evaluated: ch.targetInfo.len
0
834 { -
835 timeArray = qExtractServerTime(ch.targetInfoBuff); -
836 }
never executed: }
0
837 -
838 -
839 if(timeArray.size()) {
never evaluated: timeArray.size()
0
840 ds.writeRawData(timeArray.constData(), timeArray.size()); -
841 } else {
never executed: }
0
842 QDateTime currentTime(QDate::currentDate(), -
843 QTime::currentTime(), Qt::UTC); -
844 -
845 -
846 -
847 -
848 -
849 time = static_cast<unsigned long long>(currentTime.toTime_t() + 11644473600ULL); -
850 -
851 -
852 time = static_cast<unsigned long long>(time * 10000000ULL); -
853 ds << time; -
854 }
never executed: }
0
855 -
856 -
857 QByteArray clientCh = clientChallenge(ctx); -
858 ds.writeRawData(clientCh.constData(), clientCh.size()); -
859 -
860 -
861 QByteArray reserved2(4, 0); -
862 ds.writeRawData(reserved2.constData(), reserved2.size()); -
863 -
864 if (ch.targetInfo.len > 0) {
never evaluated: ch.targetInfo.len > 0
0
865 ds.writeRawData(ch.targetInfoBuff.constData(), -
866 ch.targetInfoBuff.size()); -
867 }
never executed: }
0
868 -
869 -
870 QByteArray reserved3(4, 0); -
871 ds.writeRawData(reserved3.constData(), reserved3.size()); -
872 -
873 QByteArray message((const char*)ch.challenge, sizeof(ch.challenge)); -
874 message.append(temp); -
875 -
876 QByteArray ntChallengeResp = qEncodeHmacMd5(phase3->v2Hash, message); -
877 ntChallengeResp.append(temp); -
878 -
879 return ntChallengeResp;
never executed: return ntChallengeResp;
0
880} -
881 -
882static QByteArray qEncodeLmv2Response(const QAuthenticatorPrivate *ctx, -
883 const QNtlmPhase2Block& ch, -
884 QNtlmPhase3Block *phase3) -
885{ -
886 qt_noop(); -
887 -
888 qCreatev2Hash(ctx, phase3); -
889 -
890 QByteArray message((const char*)ch.challenge, sizeof(ch.challenge)); -
891 QByteArray clientCh = clientChallenge(ctx); -
892 -
893 message.append(clientCh); -
894 -
895 QByteArray lmChallengeResp = qEncodeHmacMd5(phase3->v2Hash, message); -
896 lmChallengeResp.append(clientCh); -
897 -
898 return lmChallengeResp;
never executed: return lmChallengeResp;
0
899} -
900 -
901static bool qNtlmDecodePhase2(const QByteArray& data, QNtlmPhase2Block& ch) -
902{ -
903 qt_noop(); -
904 if (data.size() < QNtlmPhase2BlockBase::Size)
never evaluated: data.size() < QNtlmPhase2BlockBase::Size
0
905 return false;
never executed: return false;
0
906 -
907 -
908 QDataStream ds(data); -
909 ds.setByteOrder(QDataStream::LittleEndian); -
910 if (ds.readRawData(ch.magic, 8) < 8)
never evaluated: ds.readRawData(ch.magic, 8) < 8
0
911 return false;
never executed: return false;
0
912 if (strncmp(ch.magic, "NTLMSSP", 8) != 0)
never evaluated: strncmp(ch.magic, "NTLMSSP", 8) != 0
0
913 return false;
never executed: return false;
0
914 -
915 ds >> ch.type; -
916 if (ch.type != 2)
never evaluated: ch.type != 2
0
917 return false;
never executed: return false;
0
918 -
919 ds >> ch.targetName; -
920 ds >> ch.flags; -
921 if (ds.readRawData((char *)ch.challenge, 8) < 8)
never evaluated: ds.readRawData((char *)ch.challenge, 8) < 8
0
922 return false;
never executed: return false;
0
923 ds >> ch.context[0] >> ch.context[1]; -
924 ds >> ch.targetInfo; -
925 -
926 if (ch.targetName.len > 0) {
never evaluated: ch.targetName.len > 0
0
927 if (ch.targetName.len + ch.targetName.offset >= (unsigned)data.size())
never evaluated: ch.targetName.len + ch.targetName.offset >= (unsigned)data.size()
0
928 return false;
never executed: return false;
0
929 -
930 ch.targetNameStr = qStringFromUcs2Le(data.mid(ch.targetName.offset, ch.targetName.len)); -
931 }
never executed: }
0
932 -
933 if (ch.targetInfo.len > 0) {
never evaluated: ch.targetInfo.len > 0
0
934 if (ch.targetInfo.len + ch.targetInfo.offset > (unsigned)data.size())
never evaluated: ch.targetInfo.len + ch.targetInfo.offset > (unsigned)data.size()
0
935 return false;
never executed: return false;
0
936 -
937 ch.targetInfoBuff = data.mid(ch.targetInfo.offset, ch.targetInfo.len); -
938 }
never executed: }
0
939 -
940 return true;
never executed: return true;
0
941} -
942 -
943 -
944static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data) -
945{ -
946 QNtlmPhase2Block ch; -
947 if (!qNtlmDecodePhase2(phase2data, ch))
never evaluated: !qNtlmDecodePhase2(phase2data, ch)
0
948 return QByteArray();
never executed: return QByteArray();
0
949 -
950 QByteArray rc; -
951 QDataStream ds(&rc, QIODevice::WriteOnly); -
952 ds.setByteOrder(QDataStream::LittleEndian); -
953 QNtlmPhase3Block pb; -
954 -
955 bool unicode = ch.flags & 0x00000001; -
956 -
957 pb.flags = 0x00000200; -
958 if (unicode)
never evaluated: unicode
0
959 pb.flags |= 0x00000001;
never executed: pb.flags |= 0x00000001;
0
960 else -
961 pb.flags |= 0x00000002;
never executed: pb.flags |= 0x00000002;
0
962 -
963 -
964 int offset = QNtlmPhase3BlockBase::Size; -
965 qt_noop(); -
966 -
967 -
968 if (ctx->userDomain.isEmpty() && !ctx->extractedUser.contains(QLatin1Char('@'))) {
never evaluated: ctx->userDomain.isEmpty()
never evaluated: !ctx->extractedUser.contains(QLatin1Char('@'))
0
969 offset = qEncodeNtlmString(pb.domain, offset, ch.targetNameStr, unicode); -
970 pb.domainStr = ch.targetNameStr; -
971 } else {
never executed: }
0
972 offset = qEncodeNtlmString(pb.domain, offset, ctx->userDomain, unicode); -
973 pb.domainStr = ctx->userDomain; -
974 }
never executed: }
0
975 -
976 offset = qEncodeNtlmString(pb.user, offset, ctx->extractedUser, unicode); -
977 pb.userStr = ctx->extractedUser; -
978 -
979 offset = qEncodeNtlmString(pb.workstation, offset, ctx->workstation, unicode); -
980 pb.workstationStr = ctx->workstation; -
981 -
982 -
983 -
984 -
985 -
986 if (ch.targetInfo.len > 0) {
never evaluated: ch.targetInfo.len > 0
0
987 pb.lmResponseBuf = QByteArray(); -
988 } else {
never executed: }
0
989 pb.lmResponseBuf = qEncodeLmv2Response(ctx, ch, &pb); -
990 }
never executed: }
0
991 -
992 offset = qEncodeNtlmBuffer(pb.lmResponse, offset, pb.lmResponseBuf); -
993 -
994 -
995 -
996 -
997 -
998 pb.ntlmResponseBuf = qEncodeNtlmv2Response(ctx, ch, &pb); -
999 -
1000 offset = qEncodeNtlmBuffer(pb.ntlmResponse, offset, pb.ntlmResponseBuf); -
1001 -
1002 -
1003 -
1004 ds << pb; -
1005 -
1006 return rc;
never executed: return rc;
0
1007} -
1008 -
1009 -
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial