OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // See "SSPI Sample Application" at | 5 // See "SSPI Sample Application" at |
6 // http://msdn.microsoft.com/en-us/library/aa918273.aspx | 6 // http://msdn.microsoft.com/en-us/library/aa918273.aspx |
7 | 7 |
8 #include "net/http/http_auth_sspi_win.h" | 8 #include "net/http/http_auth_sspi_win.h" |
9 | 9 |
10 #include "base/base64.h" | 10 #include "base/base64.h" |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 if (!SecIsValidHandle(&ctxt_)) { | 285 if (!SecIsValidHandle(&ctxt_)) { |
286 return net::ParseFirstRoundChallenge(scheme_, tok); | 286 return net::ParseFirstRoundChallenge(scheme_, tok); |
287 } | 287 } |
288 std::string encoded_auth_token; | 288 std::string encoded_auth_token; |
289 return net::ParseLaterRoundChallenge(scheme_, tok, &encoded_auth_token, | 289 return net::ParseLaterRoundChallenge(scheme_, tok, &encoded_auth_token, |
290 &decoded_server_auth_token_); | 290 &decoded_server_auth_token_); |
291 } | 291 } |
292 | 292 |
293 int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials, | 293 int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials, |
294 const std::string& spn, | 294 const std::string& spn, |
| 295 const std::string& channel_bindings, |
295 std::string* auth_token, | 296 std::string* auth_token, |
296 const CompletionCallback& /*callback*/) { | 297 const CompletionCallback& /*callback*/) { |
297 // Initial challenge. | 298 // Initial challenge. |
298 if (!SecIsValidHandle(&cred_)) { | 299 if (!SecIsValidHandle(&cred_)) { |
299 int rv = OnFirstRound(credentials); | 300 int rv = OnFirstRound(credentials); |
300 if (rv != OK) | 301 if (rv != OK) |
301 return rv; | 302 return rv; |
302 } | 303 } |
303 | 304 |
304 DCHECK(SecIsValidHandle(&cred_)); | 305 DCHECK(SecIsValidHandle(&cred_)); |
305 void* out_buf; | 306 void* out_buf; |
306 int out_buf_len; | 307 int out_buf_len; |
307 int rv = GetNextSecurityToken( | 308 int rv = GetNextSecurityToken( |
308 spn, | 309 spn, channel_bindings, |
309 static_cast<void *>(const_cast<char *>( | 310 static_cast<void*>(const_cast<char*>(decoded_server_auth_token_.c_str())), |
310 decoded_server_auth_token_.c_str())), | 311 decoded_server_auth_token_.length(), &out_buf, &out_buf_len); |
311 decoded_server_auth_token_.length(), | |
312 &out_buf, | |
313 &out_buf_len); | |
314 if (rv != OK) | 312 if (rv != OK) |
315 return rv; | 313 return rv; |
316 | 314 |
317 // Base64 encode data in output buffer and prepend the scheme. | 315 // Base64 encode data in output buffer and prepend the scheme. |
318 std::string encode_input(static_cast<char*>(out_buf), out_buf_len); | 316 std::string encode_input(static_cast<char*>(out_buf), out_buf_len); |
319 std::string encode_output; | 317 std::string encode_output; |
320 base::Base64Encode(encode_input, &encode_output); | 318 base::Base64Encode(encode_input, &encode_output); |
321 // OK, we are done with |out_buf| | 319 // OK, we are done with |out_buf| |
322 free(out_buf); | 320 free(out_buf); |
323 *auth_token = scheme_ + " " + encode_output; | 321 *auth_token = scheme_ + " " + encode_output; |
(...skipping 13 matching lines...) Expand all Loading... |
337 return rv; | 335 return rv; |
338 } else { | 336 } else { |
339 rv = AcquireDefaultCredentials(library_, security_package_, &cred_); | 337 rv = AcquireDefaultCredentials(library_, security_package_, &cred_); |
340 if (rv != OK) | 338 if (rv != OK) |
341 return rv; | 339 return rv; |
342 } | 340 } |
343 | 341 |
344 return rv; | 342 return rv; |
345 } | 343 } |
346 | 344 |
347 int HttpAuthSSPI::GetNextSecurityToken( | 345 int HttpAuthSSPI::GetNextSecurityToken(const std::string& spn, |
348 const std::string& spn, | 346 const std::string& channel_bindings, |
349 const void* in_token, | 347 const void* in_token, |
350 int in_token_len, | 348 int in_token_len, |
351 void** out_token, | 349 void** out_token, |
352 int* out_token_len) { | 350 int* out_token_len) { |
353 CtxtHandle* ctxt_ptr; | 351 CtxtHandle* ctxt_ptr = nullptr; |
354 SecBufferDesc in_buffer_desc, out_buffer_desc; | 352 SecBufferDesc in_buffer_desc, out_buffer_desc; |
355 SecBufferDesc* in_buffer_desc_ptr; | 353 SecBufferDesc* in_buffer_desc_ptr = nullptr; |
356 SecBuffer in_buffer, out_buffer; | 354 SecBuffer in_buffers[2], out_buffer; |
357 | 355 |
| 356 in_buffer_desc.ulVersion = SECBUFFER_VERSION; |
| 357 in_buffer_desc.cBuffers = 0; |
| 358 in_buffer_desc.pBuffers = in_buffers; |
358 if (in_token_len > 0) { | 359 if (in_token_len > 0) { |
359 // Prepare input buffer. | 360 // Prepare input buffer. |
360 in_buffer_desc.ulVersion = SECBUFFER_VERSION; | 361 SecBuffer& sec_buffer = in_buffers[in_buffer_desc.cBuffers++]; |
361 in_buffer_desc.cBuffers = 1; | 362 sec_buffer.BufferType = SECBUFFER_TOKEN; |
362 in_buffer_desc.pBuffers = &in_buffer; | 363 sec_buffer.cbBuffer = in_token_len; |
363 in_buffer.BufferType = SECBUFFER_TOKEN; | 364 sec_buffer.pvBuffer = const_cast<void*>(in_token); |
364 in_buffer.cbBuffer = in_token_len; | |
365 in_buffer.pvBuffer = const_cast<void*>(in_token); | |
366 ctxt_ptr = &ctxt_; | 365 ctxt_ptr = &ctxt_; |
367 in_buffer_desc_ptr = &in_buffer_desc; | |
368 } else { | 366 } else { |
369 // If there is no input token, then we are starting a new authentication | 367 // If there is no input token, then we are starting a new authentication |
370 // sequence. If we have already initialized our security context, then | 368 // sequence. If we have already initialized our security context, then |
371 // we're incorrectly reusing the auth handler for a new sequence. | 369 // we're incorrectly reusing the auth handler for a new sequence. |
372 if (SecIsValidHandle(&ctxt_)) { | 370 if (SecIsValidHandle(&ctxt_)) { |
373 NOTREACHED(); | 371 NOTREACHED(); |
374 return ERR_UNEXPECTED; | 372 return ERR_UNEXPECTED; |
375 } | 373 } |
376 ctxt_ptr = NULL; | |
377 in_buffer_desc_ptr = NULL; | |
378 } | 374 } |
379 | 375 |
| 376 std::vector<char> sec_channel_bindings_buffer; |
| 377 if (!channel_bindings.empty()) { |
| 378 sec_channel_bindings_buffer.reserve(sizeof(SEC_CHANNEL_BINDINGS) + |
| 379 channel_bindings.size()); |
| 380 sec_channel_bindings_buffer.resize(sizeof(SEC_CHANNEL_BINDINGS)); |
| 381 SEC_CHANNEL_BINDINGS* bindings_desc = |
| 382 reinterpret_cast<SEC_CHANNEL_BINDINGS*>( |
| 383 &sec_channel_bindings_buffer.front()); |
| 384 bindings_desc->cbApplicationDataLength = channel_bindings.size(); |
| 385 bindings_desc->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS); |
| 386 sec_channel_bindings_buffer.insert(sec_channel_bindings_buffer.end(), |
| 387 channel_bindings.begin(), |
| 388 channel_bindings.end()); |
| 389 DCHECK_EQ(sizeof(SEC_CHANNEL_BINDINGS) + channel_bindings.size(), |
| 390 sec_channel_bindings_buffer.size()); |
| 391 |
| 392 SecBuffer& sec_buffer = in_buffers[in_buffer_desc.cBuffers++]; |
| 393 sec_buffer.BufferType = SECBUFFER_CHANNEL_BINDINGS; |
| 394 sec_buffer.cbBuffer = sec_channel_bindings_buffer.size(); |
| 395 sec_buffer.pvBuffer = &sec_channel_bindings_buffer.front(); |
| 396 } |
| 397 |
| 398 if (in_buffer_desc.cBuffers > 0) |
| 399 in_buffer_desc_ptr = &in_buffer_desc; |
| 400 |
380 // Prepare output buffer. | 401 // Prepare output buffer. |
381 out_buffer_desc.ulVersion = SECBUFFER_VERSION; | 402 out_buffer_desc.ulVersion = SECBUFFER_VERSION; |
382 out_buffer_desc.cBuffers = 1; | 403 out_buffer_desc.cBuffers = 1; |
383 out_buffer_desc.pBuffers = &out_buffer; | 404 out_buffer_desc.pBuffers = &out_buffer; |
384 out_buffer.BufferType = SECBUFFER_TOKEN; | 405 out_buffer.BufferType = SECBUFFER_TOKEN; |
385 out_buffer.cbBuffer = max_token_length_; | 406 out_buffer.cbBuffer = max_token_length_; |
386 out_buffer.pvBuffer = malloc(out_buffer.cbBuffer); | 407 out_buffer.pvBuffer = malloc(out_buffer.cbBuffer); |
387 if (!out_buffer.pvBuffer) | 408 if (!out_buffer.pvBuffer) |
388 return ERR_OUT_OF_MEMORY; | 409 return ERR_OUT_OF_MEMORY; |
389 | 410 |
390 DWORD context_flags = 0; | 411 DWORD context_flags = 0; |
391 // Firefox only sets ISC_REQ_DELEGATE, but MSDN documentation indicates that | 412 // Firefox only sets ISC_REQ_DELEGATE, but MSDN documentation indicates that |
392 // ISC_REQ_MUTUAL_AUTH must also be set. | 413 // ISC_REQ_MUTUAL_AUTH must also be set. |
393 if (can_delegate_) | 414 if (can_delegate_) |
394 context_flags |= (ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH); | 415 context_flags |= (ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH); |
395 | 416 |
396 // This returns a token that is passed to the remote server. | 417 // This returns a token that is passed to the remote server. |
397 DWORD context_attribute; | 418 DWORD context_attribute; |
398 base::string16 spn16 = base::ASCIIToUTF16(spn); | 419 base::string16 spn16 = base::ASCIIToUTF16(spn); |
399 SECURITY_STATUS status = library_->InitializeSecurityContext( | 420 SECURITY_STATUS status = library_->InitializeSecurityContext( |
400 &cred_, // phCredential | 421 &cred_, // phCredential |
401 ctxt_ptr, // phContext | 422 ctxt_ptr, // phContext |
402 const_cast<base::char16*>(spn16.c_str()), // pszTargetName | 423 const_cast<base::char16*>(spn16.c_str()), // pszTargetName |
403 context_flags, // fContextReq | 424 context_flags, // fContextReq |
404 0, // Reserved1 (must be 0) | 425 0, // Reserved1 (must be 0) |
405 SECURITY_NATIVE_DREP, // TargetDataRep | 426 SECURITY_NATIVE_DREP, // TargetDataRep |
406 in_buffer_desc_ptr, // pInput | 427 in_buffer_desc_ptr, // pInput |
407 0, // Reserved2 (must be 0) | 428 0, // Reserved2 (must be 0) |
408 &ctxt_, // phNewContext | 429 &ctxt_, // phNewContext |
409 &out_buffer_desc, // pOutput | 430 &out_buffer_desc, // pOutput |
410 &context_attribute, // pfContextAttr | 431 &context_attribute, // pfContextAttr |
411 NULL); // ptsExpiry | 432 nullptr); // ptsExpiry |
412 int rv = MapInitializeSecurityContextStatusToError(status); | 433 int rv = MapInitializeSecurityContextStatusToError(status); |
413 if (rv != OK) { | 434 if (rv != OK) { |
414 ResetSecurityContext(); | 435 ResetSecurityContext(); |
415 free(out_buffer.pvBuffer); | 436 free(out_buffer.pvBuffer); |
416 return rv; | 437 return rv; |
417 } | 438 } |
418 if (!out_buffer.cbBuffer) { | 439 if (!out_buffer.cbBuffer) { |
419 free(out_buffer.pvBuffer); | 440 free(out_buffer.pvBuffer); |
420 out_buffer.pvBuffer = NULL; | 441 out_buffer.pvBuffer = NULL; |
421 } | 442 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 int token_length = pkg_info->cbMaxToken; | 475 int token_length = pkg_info->cbMaxToken; |
455 status = library->FreeContextBuffer(pkg_info); | 476 status = library->FreeContextBuffer(pkg_info); |
456 rv = MapFreeContextBufferStatusToError(status); | 477 rv = MapFreeContextBufferStatusToError(status); |
457 if (rv != OK) | 478 if (rv != OK) |
458 return rv; | 479 return rv; |
459 *max_token_length = token_length; | 480 *max_token_length = token_length; |
460 return OK; | 481 return OK; |
461 } | 482 } |
462 | 483 |
463 } // namespace net | 484 } // namespace net |
OLD | NEW |