summaryrefslogtreecommitdiff
path: root/chromium/net/http/mock_sspi_library_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/http/mock_sspi_library_win.cc')
-rw-r--r--chromium/net/http/mock_sspi_library_win.cc206
1 files changed, 191 insertions, 15 deletions
diff --git a/chromium/net/http/mock_sspi_library_win.cc b/chromium/net/http/mock_sspi_library_win.cc
index 1d3379cd278..95a3deb27f4 100644
--- a/chromium/net/http/mock_sspi_library_win.cc
+++ b/chromium/net/http/mock_sspi_library_win.cc
@@ -4,16 +4,108 @@
#include "net/http/mock_sspi_library_win.h"
+#include <algorithm>
+#include <cstring>
+#include <memory>
+
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
+// Comparator so we can use CredHandle and CtxtHandle with std::set. Both of
+// those classes are typedefs for _SecHandle.
+bool operator<(const _SecHandle left, const _SecHandle right) {
+ return left.dwUpper < right.dwUpper || left.dwLower < right.dwLower;
+}
+
namespace net {
+namespace {
+
+int uniquifier_ = 0;
+
+struct MockCredential {
+ base::string16 source_principal;
+ base::string16 package;
+ bool has_explicit_credentials = false;
+ int uniquifier = ++uniquifier_;
+
+ // CredHandle and CtxtHandle both shared the following definition:
+ //
+ // typedef struct _SecHandle {
+ // ULONG_PTR dwLower;
+ // ULONG_PTR dwUpper;
+ // } SecHandle, * PSecHandle;
+ //
+ // ULONG_PTR type can hold a pointer. This function stuffs |this| into dwUpper
+ // and adds a uniquifier to dwLower. This ensures that all PCredHandles issued
+ // by this method during the lifetime of this process is unique.
+ void StoreInHandle(PCredHandle handle) {
+ DCHECK(uniquifier > 0);
+ EXPECT_FALSE(SecIsValidHandle(handle));
+
+ handle->dwLower = uniquifier;
+ handle->dwUpper = reinterpret_cast<ULONG_PTR>(this);
+
+ DCHECK(SecIsValidHandle(handle));
+ }
+
+ static MockCredential* FromHandle(PCredHandle handle) {
+ return reinterpret_cast<MockCredential*>(handle->dwUpper);
+ }
+};
+
+struct MockContext {
+ MockCredential* credential = nullptr;
+ base::string16 target_principal;
+ int uniquifier = ++uniquifier_;
+ int rounds = 0;
+
+ // CredHandle and CtxtHandle both shared the following definition:
+ //
+ // typedef struct _SecHandle {
+ // ULONG_PTR dwLower;
+ // ULONG_PTR dwUpper;
+ // } SecHandle, * PSecHandle;
+ //
+ // ULONG_PTR type can hold a pointer. This function stuffs |this| into dwUpper
+ // and adds a uniquifier to dwLower. This ensures that all PCredHandles issued
+ // by this method during the lifetime of this process is unique.
+ void StoreInHandle(PCtxtHandle handle) {
+ EXPECT_FALSE(SecIsValidHandle(handle));
+ DCHECK(uniquifier > 0);
+
+ handle->dwLower = uniquifier;
+ handle->dwUpper = reinterpret_cast<ULONG_PTR>(this);
+
+ DCHECK(SecIsValidHandle(handle));
+ }
+
+ std::string ToString() const {
+ return base::StringPrintf(
+ "%s's token #%d for %S",
+ base::UTF16ToUTF8(credential->source_principal).c_str(), rounds + 1,
+ base::as_wcstr(target_principal));
+ }
+
+ static MockContext* FromHandle(PCtxtHandle handle) {
+ return reinterpret_cast<MockContext*>(handle->dwUpper);
+ }
+};
+
+} // namespace
+
MockSSPILibrary::MockSSPILibrary() {
}
MockSSPILibrary::~MockSSPILibrary() {
EXPECT_TRUE(expected_package_queries_.empty());
EXPECT_TRUE(expected_freed_packages_.empty());
+ EXPECT_TRUE(active_credentials_.empty());
+ EXPECT_TRUE(active_contexts_.empty());
}
SECURITY_STATUS MockSSPILibrary::AcquireCredentialsHandle(
@@ -26,8 +118,21 @@ SECURITY_STATUS MockSSPILibrary::AcquireCredentialsHandle(
void* pvGetKeyArgument,
PCredHandle phCredential,
PTimeStamp ptsExpiry) {
- // Fill in phCredential with arbitrary value.
- phCredential->dwLower = phCredential->dwUpper = ((ULONG_PTR) ((INT_PTR)0));
+ DCHECK(!SecIsValidHandle(phCredential));
+ auto* credential = new MockCredential;
+ credential->source_principal = pszPrincipal ? base::as_u16cstr(pszPrincipal)
+ : STRING16_LITERAL("<Default>");
+ credential->package = base::as_u16cstr(pszPackage);
+ credential->has_explicit_credentials = !!pvAuthData;
+
+ credential->StoreInHandle(phCredential);
+
+ if (ptsExpiry) {
+ ptsExpiry->LowPart = 0xBAA5B780;
+ ptsExpiry->HighPart = 0x01D54E17;
+ }
+
+ active_credentials_.insert(*phCredential);
return SEC_E_OK;
}
@@ -44,19 +149,88 @@ SECURITY_STATUS MockSSPILibrary::InitializeSecurityContext(
PSecBufferDesc pOutput,
unsigned long* contextAttr,
PTimeStamp ptsExpiry) {
- // Fill in the outbound buffer with garbage data.
+ MockContext* new_context = new MockContext;
+ new_context->credential = MockCredential::FromHandle(phCredential);
+ new_context->target_principal = base::as_u16cstr(pszTargetName);
+ new_context->rounds = 0;
+
+ // Always rotate contexts. That way tests will fail if the caller's context
+ // management is broken.
+ if (phContext && SecIsValidHandle(phContext)) {
+ std::unique_ptr<MockContext> old_context{
+ MockContext::FromHandle(phContext)};
+ EXPECT_EQ(old_context->credential, new_context->credential);
+ EXPECT_EQ(1u, active_contexts_.erase(*phContext));
+
+ new_context->rounds = old_context->rounds + 1;
+ SecInvalidateHandle(phContext);
+ }
+
+ new_context->StoreInHandle(phNewContext);
+ active_contexts_.insert(*phNewContext);
+
+ auto token = new_context->ToString();
PSecBuffer out_buffer = pOutput->pBuffers;
- out_buffer->cbBuffer = 2;
- uint8_t* buf = reinterpret_cast<uint8_t*>(out_buffer->pvBuffer);
- buf[0] = 0xAB;
- buf[1] = 0xBA;
-
- // Fill in phNewContext with arbitrary value if it's invalid.
- if (phNewContext != phContext)
- phNewContext->dwLower = phNewContext->dwUpper = ((ULONG_PTR) ((INT_PTR)0));
+ out_buffer->cbBuffer = std::min<ULONG>(out_buffer->cbBuffer, token.size());
+ std::memcpy(out_buffer->pvBuffer, token.data(), out_buffer->cbBuffer);
+
+ if (ptsExpiry) {
+ ptsExpiry->LowPart = 0xBAA5B780;
+ ptsExpiry->HighPart = 0x01D54E15;
+ }
return SEC_E_OK;
}
+SECURITY_STATUS MockSSPILibrary::QueryContextAttributesEx(PCtxtHandle phContext,
+ ULONG ulAttribute,
+ PVOID pBuffer,
+ ULONG cbBuffer) {
+ static const SecPkgInfoW kNegotiatedPackage = {
+ 0,
+ 0,
+ 0,
+ 0,
+ const_cast<SEC_WCHAR*>(L"Itsa me Kerberos!!"),
+ const_cast<SEC_WCHAR*>(L"I like turtles")};
+
+ auto* context = MockContext::FromHandle(phContext);
+
+ switch (ulAttribute) {
+ case SECPKG_ATTR_NATIVE_NAMES: {
+ auto* native_names =
+ reinterpret_cast<SecPkgContext_NativeNames*>(pBuffer);
+ DCHECK_EQ(sizeof(*native_names), cbBuffer);
+ native_names->sClientName =
+ base::as_writable_wcstr(context->credential->source_principal);
+ native_names->sServerName =
+ base::as_writable_wcstr(context->target_principal);
+ return SEC_E_OK;
+ }
+
+ case SECPKG_ATTR_NEGOTIATION_INFO: {
+ auto* negotiation_info =
+ reinterpret_cast<SecPkgContext_NegotiationInfo*>(pBuffer);
+ DCHECK_EQ(sizeof(*negotiation_info), cbBuffer);
+ negotiation_info->PackageInfo =
+ const_cast<SecPkgInfoW*>(&kNegotiatedPackage);
+ negotiation_info->NegotiationState = (context->rounds == 1)
+ ? SECPKG_NEGOTIATION_COMPLETE
+ : SECPKG_NEGOTIATION_IN_PROGRESS;
+ return SEC_E_OK;
+ }
+
+ case SECPKG_ATTR_AUTHORITY: {
+ auto* authority = reinterpret_cast<SecPkgContext_Authority*>(pBuffer);
+ DCHECK_EQ(sizeof(*authority), cbBuffer);
+ authority->sAuthorityName = const_cast<SEC_WCHAR*>(L"Dodgy Server");
+ return SEC_E_OK;
+ }
+
+ default:
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+}
+
SECURITY_STATUS MockSSPILibrary::QuerySecurityPackageInfo(
LPWSTR pszPackageName, PSecPkgInfoW *pkgInfo) {
EXPECT_TRUE(!expected_package_queries_.empty());
@@ -72,15 +246,17 @@ SECURITY_STATUS MockSSPILibrary::QuerySecurityPackageInfo(
SECURITY_STATUS MockSSPILibrary::FreeCredentialsHandle(
PCredHandle phCredential) {
- EXPECT_TRUE(phCredential->dwLower == ((ULONG_PTR) ((INT_PTR) 0)));
- EXPECT_TRUE(phCredential->dwUpper == ((ULONG_PTR) ((INT_PTR) 0)));
+ DCHECK(SecIsValidHandle(phCredential));
+ EXPECT_EQ(1u, active_credentials_.erase(*phCredential));
+ std::unique_ptr<MockCredential> owned{
+ MockCredential::FromHandle(phCredential)};
SecInvalidateHandle(phCredential);
return SEC_E_OK;
}
SECURITY_STATUS MockSSPILibrary::DeleteSecurityContext(PCtxtHandle phContext) {
- EXPECT_TRUE(phContext->dwLower == ((ULONG_PTR) ((INT_PTR) 0)));
- EXPECT_TRUE(phContext->dwUpper == ((ULONG_PTR) ((INT_PTR) 0)));
+ std::unique_ptr<MockContext> context{MockContext::FromHandle(phContext)};
+ EXPECT_EQ(1u, active_contexts_.erase(*phContext));
SecInvalidateHandle(phContext);
return SEC_E_OK;
}