|
Lines 155-160
public:
Link Here
|
| 155 |
TQString out_mech; |
155 |
TQString out_mech; |
| 156 |
TQByteArray out_buf; |
156 |
TQByteArray out_buf; |
| 157 |
bool capable; |
157 |
bool capable; |
|
|
158 |
bool allow_plain; |
| 158 |
int err; |
159 |
int err; |
| 159 |
|
160 |
|
| 160 |
TQCA_SASLNeedParams need; |
161 |
TQCA_SASLNeedParams need; |
|
Lines 207-218
public:
Link Here
|
| 207 |
host = _host; |
208 |
host = _host; |
| 208 |
} |
209 |
} |
| 209 |
|
210 |
|
| 210 |
void setSecurityProps(bool, bool, bool, bool, bool reqForward, bool reqCreds, bool reqMutual, int ssfMin, int, const TQString &, int) |
211 |
void setSecurityProps(bool noPlain, bool, bool, bool, bool reqForward, bool reqCreds, bool reqMutual, int ssfMin, int, const TQString &, int) |
| 211 |
{ |
212 |
{ |
| 212 |
if(reqForward || reqCreds || reqMutual || ssfMin > 0) |
213 |
if(reqForward || reqCreds || reqMutual || ssfMin > 0) |
| 213 |
capable = false; |
214 |
capable = false; |
| 214 |
else |
215 |
else |
| 215 |
capable = true; |
216 |
capable = true; |
|
|
217 |
allow_plain = !noPlain; |
| 216 |
} |
218 |
} |
| 217 |
|
219 |
|
| 218 |
int security() const |
220 |
int security() const |
|
Lines 228-235
public:
Link Here
|
| 228 |
bool clientStart(const TQStringList &mechlist) |
230 |
bool clientStart(const TQStringList &mechlist) |
| 229 |
{ |
231 |
{ |
| 230 |
bool haveMech = false; |
232 |
bool haveMech = false; |
|
|
233 |
resetState(); |
| 234 |
step = 0; |
| 235 |
|
| 231 |
for(TQStringList::ConstIterator it = mechlist.begin(); it != mechlist.end(); ++it) { |
236 |
for(TQStringList::ConstIterator it = mechlist.begin(); it != mechlist.end(); ++it) { |
|
|
237 |
if((*it) == "PLAIN" && allow_plain) { |
| 238 |
out_mech = "PLAIN"; |
| 239 |
haveMech = true; |
| 240 |
break; |
| 241 |
} |
| 232 |
if((*it) == "DIGEST-MD5") { |
242 |
if((*it) == "DIGEST-MD5") { |
|
|
243 |
out_mech = "DIGEST-MD5"; |
| 233 |
haveMech = true; |
244 |
haveMech = true; |
| 234 |
break; |
245 |
break; |
| 235 |
} |
246 |
} |
|
Lines 238-246
public:
Link Here
|
| 238 |
err = TQCA::SASL::NoMech; |
249 |
err = TQCA::SASL::NoMech; |
| 239 |
return false; |
250 |
return false; |
| 240 |
} |
251 |
} |
| 241 |
|
|
|
| 242 |
resetState(); |
| 243 |
step = 0; |
| 244 |
return true; |
252 |
return true; |
| 245 |
} |
253 |
} |
| 246 |
|
254 |
|
|
Lines 316-322
public:
Link Here
|
| 316 |
|
324 |
|
| 317 |
const TQByteArray *clientInit() const |
325 |
const TQByteArray *clientInit() const |
| 318 |
{ |
326 |
{ |
| 319 |
return 0; |
327 |
return out_mech == "PLAIN" ? &out_buf : 0; |
| 320 |
} |
328 |
} |
| 321 |
|
329 |
|
| 322 |
TQByteArray result() const |
330 |
TQByteArray result() const |
|
Lines 326-410
public:
Link Here
|
| 326 |
|
334 |
|
| 327 |
int clientTryAgain() |
335 |
int clientTryAgain() |
| 328 |
{ |
336 |
{ |
| 329 |
if(step == 0) { |
337 |
if( out_mech == "PLAIN" ) { |
| 330 |
out_mech = "DIGEST-MD5"; |
338 |
if(step == 0) { |
| 331 |
++step; |
339 |
// First, check if we have everything |
| 332 |
return Continue; |
340 |
if(need.user || need.pass) { |
|
|
341 |
err = -1; |
| 342 |
return Error; |
| 343 |
} |
| 344 |
if(!have.user) { |
| 345 |
need.user = true; |
| 346 |
} |
| 347 |
if(!have.pass) { |
| 348 |
need.pass = true; |
| 349 |
} |
| 350 |
if(need.user || need.pass) { |
| 351 |
return NeedParams; |
| 352 |
} |
| 353 |
|
| 354 |
TQCString authz_ = authz.utf8(); |
| 355 |
TQCString user_ = user.utf8(); |
| 356 |
TQCString pass_ = pass.utf8(); |
| 357 |
int l = 0; |
| 358 |
|
| 359 |
out_buf.resize(authz_.length() + 1 + user_.length() + 1 + pass_.length()); |
| 360 |
memcpy(&out_buf[l], authz_.data(), authz_.length()); |
| 361 |
l += authz_.length(); |
| 362 |
out_buf[l] = '\0'; |
| 363 |
l += 1; |
| 364 |
memcpy(&out_buf[l], user_.data(), user_.length()); |
| 365 |
l += user_.length(); |
| 366 |
out_buf[l] = '\0'; |
| 367 |
l += 1; |
| 368 |
|
| 369 |
memcpy(&out_buf[l], pass_.data(), pass_.length()); |
| 370 |
++step; |
| 371 |
return Continue; |
| 372 |
} |
| 373 |
|
| 374 |
out_buf.resize(0); |
| 375 |
return Success; |
| 333 |
} |
376 |
} |
| 334 |
else if(step == 1) { |
377 |
|
| 335 |
// if we still need params, then the app has failed us! |
378 |
if( out_mech == "DIGEST-MD5" ) { |
| 336 |
if(need.user || need.authzid || need.pass || need.realm) { |
379 |
if(step == 0) { |
| 337 |
err = -1; |
380 |
++step; |
| 338 |
return Error; |
381 |
return Continue; |
| 339 |
} |
382 |
} |
|
|
383 |
else if(step == 1) { |
| 384 |
// if we still need params, then the app has failed us! |
| 385 |
if(need.user || need.authzid || need.pass || need.realm) { |
| 386 |
err = -1; |
| 387 |
return Error; |
| 388 |
} |
| 340 |
|
389 |
|
| 341 |
// see if some params are needed |
390 |
// see if some params are needed |
| 342 |
if(!have.user) |
391 |
if(!have.user) |
| 343 |
need.user = true; |
392 |
need.user = true; |
| 344 |
if(!have.authzid) |
393 |
if(!have.authzid) |
| 345 |
need.authzid = true; |
394 |
need.authzid = true; |
| 346 |
if(!have.pass) |
395 |
if(!have.pass) |
| 347 |
need.pass = true; |
396 |
need.pass = true; |
| 348 |
if(need.user || need.authzid || need.pass) |
397 |
if(need.user || need.authzid || need.pass) |
| 349 |
return NeedParams; |
398 |
return NeedParams; |
| 350 |
|
399 |
|
| 351 |
// get props |
400 |
// get props |
| 352 |
TQCString cs(in_buf.data(), in_buf.size()+1); |
401 |
TQCString cs(in_buf.data(), in_buf.size()+1); |
| 353 |
PropList in; |
402 |
PropList in; |
| 354 |
if(!in.fromString(cs)) { |
403 |
if(!in.fromString(cs)) { |
| 355 |
err = TQCA::SASL::BadProto; |
404 |
err = TQCA::SASL::BadProto; |
| 356 |
return Error; |
405 |
return Error; |
|
|
406 |
} |
| 407 |
|
| 408 |
// make a cnonce |
| 409 |
TQByteArray a(32); |
| 410 |
for(int n = 0; n < (int)a.size(); ++n) |
| 411 |
a[n] = (char)(256.0*rand()/(RAND_MAX+1.0)); |
| 412 |
TQCString cnonce = Base64::arrayToString(a).latin1(); |
| 413 |
|
| 414 |
// make other variables |
| 415 |
realm = host; |
| 416 |
TQCString nonce = in.get("nonce"); |
| 417 |
TQCString nc = "00000001"; |
| 418 |
TQCString uri = service.utf8() + '/' + host.utf8(); |
| 419 |
TQCString qop = "auth"; |
| 420 |
|
| 421 |
// build 'response' |
| 422 |
TQCString X = user.utf8() + ':' + realm.utf8() + ':' + pass.utf8(); |
| 423 |
TQByteArray Y = TQCA::MD5::hash(X); |
| 424 |
TQCString tmp = TQCString(":") + nonce + ':' + cnonce + ':' + authz.utf8(); |
| 425 |
TQByteArray A1(Y.size() + tmp.length()); |
| 426 |
memcpy(A1.data(), Y.data(), Y.size()); |
| 427 |
memcpy(A1.data() + Y.size(), tmp.data(), tmp.length()); |
| 428 |
TQCString A2 = "AUTHENTICATE:" + uri; |
| 429 |
TQCString HA1 = TQCA::MD5::hashToString(A1).latin1(); |
| 430 |
TQCString HA2 = TQCA::MD5::hashToString(A2).latin1(); |
| 431 |
TQCString KD = HA1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + HA2; |
| 432 |
TQCString Z = TQCA::MD5::hashToString(KD).latin1(); |
| 433 |
|
| 434 |
// build output |
| 435 |
PropList out; |
| 436 |
out.set("username", user.utf8()); |
| 437 |
out.set("realm", host.utf8()); |
| 438 |
out.set("nonce", nonce); |
| 439 |
out.set("cnonce", cnonce); |
| 440 |
out.set("nc", nc); |
| 441 |
out.set("serv-type", service.utf8()); |
| 442 |
out.set("host", host.utf8()); |
| 443 |
out.set("digest-uri", uri); |
| 444 |
out.set("qop", qop); |
| 445 |
out.set("response", Z); |
| 446 |
out.set("charset", "utf-8"); |
| 447 |
out.set("authzid", authz.utf8()); |
| 448 |
TQCString s = out.toString(); |
| 449 |
|
| 450 |
// done |
| 451 |
out_buf.resize(s.length()); |
| 452 |
memcpy(out_buf.data(), s.data(), out_buf.size()); |
| 453 |
++step; |
| 454 |
return Continue; |
| 357 |
} |
455 |
} |
| 358 |
|
456 |
|
| 359 |
// make a cnonce |
|
|
| 360 |
TQByteArray a(32); |
| 361 |
for(int n = 0; n < (int)a.size(); ++n) |
| 362 |
a[n] = (char)(256.0*rand()/(RAND_MAX+1.0)); |
| 363 |
TQCString cnonce = Base64::arrayToString(a).latin1(); |
| 364 |
|
| 365 |
// make other variables |
| 366 |
realm = host; |
| 367 |
TQCString nonce = in.get("nonce"); |
| 368 |
TQCString nc = "00000001"; |
| 369 |
TQCString uri = service.utf8() + '/' + host.utf8(); |
| 370 |
TQCString qop = "auth"; |
| 371 |
|
| 372 |
// build 'response' |
| 373 |
TQCString X = user.utf8() + ':' + realm.utf8() + ':' + pass.utf8(); |
| 374 |
TQByteArray Y = TQCA::MD5::hash(X); |
| 375 |
TQCString tmp = TQCString(":") + nonce + ':' + cnonce + ':' + authz.utf8(); |
| 376 |
TQByteArray A1(Y.size() + tmp.length()); |
| 377 |
memcpy(A1.data(), Y.data(), Y.size()); |
| 378 |
memcpy(A1.data() + Y.size(), tmp.data(), tmp.length()); |
| 379 |
TQCString A2 = "AUTHENTICATE:" + uri; |
| 380 |
TQCString HA1 = TQCA::MD5::hashToString(A1).latin1(); |
| 381 |
TQCString HA2 = TQCA::MD5::hashToString(A2).latin1(); |
| 382 |
TQCString KD = HA1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + HA2; |
| 383 |
TQCString Z = TQCA::MD5::hashToString(KD).latin1(); |
| 384 |
|
| 385 |
// build output |
| 386 |
PropList out; |
| 387 |
out.set("username", user.utf8()); |
| 388 |
out.set("realm", host.utf8()); |
| 389 |
out.set("nonce", nonce); |
| 390 |
out.set("cnonce", cnonce); |
| 391 |
out.set("nc", nc); |
| 392 |
out.set("serv-type", service.utf8()); |
| 393 |
out.set("host", host.utf8()); |
| 394 |
out.set("digest-uri", uri); |
| 395 |
out.set("qop", qop); |
| 396 |
out.set("response", Z); |
| 397 |
out.set("charset", "utf-8"); |
| 398 |
out.set("authzid", authz.utf8()); |
| 399 |
TQCString s = out.toString(); |
| 400 |
|
| 401 |
// done |
| 402 |
out_buf.resize(s.length()); |
| 403 |
memcpy(out_buf.data(), s.data(), out_buf.size()); |
| 404 |
++step; |
| 405 |
return Continue; |
| 406 |
} |
| 407 |
else { |
| 408 |
out_buf.resize(0); |
457 |
out_buf.resize(0); |
| 409 |
return Success; |
458 |
return Success; |
| 410 |
} |
459 |
} |