static BOOL ensure_cred_handle(void) { SECURITY_STATUS res = SEC_E_OK; EnterCriticalSection(&init_sechandle_cs); if(!cred_handle_initialized) { SCHANNEL_CRED cred = {SCHANNEL_CRED_VERSION}; SecPkgCred_SupportedProtocols prots; res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &cred_handle, NULL); if(res == SEC_E_OK) { res = QueryCredentialsAttributesA(&cred_handle, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &prots); if(res != SEC_E_OK || (prots.grbitProtocol & SP_PROT_TLS1_1PLUS_CLIENT)) { cred.grbitEnabledProtocols = prots.grbitProtocol & ~SP_PROT_TLS1_1PLUS_CLIENT; res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &compat_cred_handle, NULL); have_compat_cred_handle = res == SEC_E_OK; } } cred_handle_initialized = res == SEC_E_OK; } LeaveCriticalSection(&init_sechandle_cs); if(res != SEC_E_OK) { WARN("Failed: %08x\n", res); return FALSE; } return TRUE; }
SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleA( SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%s %s %d %p %p %p %p %p %p\n", debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (pszPackage) { UNICODE_STRING principal, package; RtlCreateUnicodeStringFromAsciiz(&principal, pszPrincipal); RtlCreateUnicodeStringFromAsciiz(&package, pszPackage); ret = AcquireCredentialsHandleW(principal.Buffer, package.Buffer, fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); RtlFreeUnicodeString(&principal); RtlFreeUnicodeString(&package); } else ret = SEC_E_SECPKG_NOT_FOUND; return ret; }
static BOOL ensure_cred_handle(void) { BOOL ret = TRUE; EnterCriticalSection(&init_sechandle_cs); if(!cred_handle_initialized) { SECURITY_STATUS res; res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &cred_handle, NULL); if(res == SEC_E_OK) { cred_handle_initialized = TRUE; } else { WARN("AcquireCredentialsHandleW failed: %u\n", res); ret = FALSE; } } LeaveCriticalSection(&init_sechandle_cs); return ret; }
int _mongoc_sspi_auth_sspi_client_init (WCHAR *service, ULONG flags, WCHAR *user, ULONG ulen, WCHAR *domain, ULONG dlen, WCHAR *password, ULONG plen, mongoc_sspi_client_state_t *state) { SECURITY_STATUS status; SEC_WINNT_AUTH_IDENTITY_W authIdentity; TimeStamp ignored; state->response = NULL; state->username = NULL; state->qop = SECQOP_WRAP_NO_ENCRYPT; state->flags = flags; state->haveCred = 0; state->haveCtx = 0; state->spn = _wcsdup (service); if (state->spn == NULL) { return MONGOC_SSPI_AUTH_GSS_ERROR; } /* Convert RFC-2078 format to SPN */ if (!wcschr (state->spn, L'/')) { WCHAR *ptr = wcschr (state->spn, L'@'); if (ptr) { *ptr = L'/'; } } if (user) { authIdentity.User = user; authIdentity.UserLength = ulen; authIdentity.Domain = domain; authIdentity.DomainLength = dlen; authIdentity.Password = password; authIdentity.PasswordLength = plen; authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; } /* Note that the first paramater, pszPrincipal, appears to be * completely ignored in the Kerberos SSP. For more details see * https://github.com/mongodb-labs/winkerberos/issues/11. * */ status = AcquireCredentialsHandleW (/* Principal */ NULL, /* Security package name */ L"kerberos", /* Credentials Use */ SECPKG_CRED_OUTBOUND, /* LogonID (We don't use this) */ NULL, /* AuthData */ user ? &authIdentity : NULL, /* Always NULL */ NULL, /* Always NULL */ NULL, /* CredHandle */ &state->cred, /* Expiry (Required but unused by us) */ &ignored); if (status != SEC_E_OK) { _mongoc_sspi_set_gsserror (status, "AcquireCredentialsHandle"); return MONGOC_SSPI_AUTH_GSS_ERROR; } state->haveCred = 1; return MONGOC_SSPI_AUTH_GSS_COMPLETE; }
bool NegotiateAuth::authorize(const AuthParams &challenge, AuthParams &authorization, const URI &uri) { SECURITY_STATUS status; std::wstring packageW = toUtf16(challenge.scheme); std::string param = challenge.base64; std::string outboundBuffer; SecBufferDesc outboundBufferDesc; SecBuffer outboundSecBuffer; TimeStamp lifetime; ULONG contextAttributes; outboundBuffer.resize(4096); outboundBufferDesc.ulVersion = 0; outboundBufferDesc.cBuffers = 1; outboundBufferDesc.pBuffers = &outboundSecBuffer; outboundSecBuffer.BufferType = SECBUFFER_TOKEN; outboundSecBuffer.pvBuffer = &outboundBuffer[0]; outboundSecBuffer.cbBuffer = (unsigned long)outboundBuffer.size(); if (param.empty()) { // No response from server; we're starting a new session if (SecIsValidHandle(&m_creds)) return false; SEC_WINNT_AUTH_IDENTITY_W id; id.User = (unsigned short *)m_username.c_str(); id.UserLength = (unsigned long)m_username.size(); id.Domain = (unsigned short *)m_domain.c_str(); id.DomainLength = (unsigned long)m_domain.size(); id.Password = (unsigned short *)m_password.c_str(); id.PasswordLength = (unsigned long)m_password.size(); id.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; status = AcquireCredentialsHandleW(NULL, (wchar_t *)packageW.c_str(), SECPKG_CRED_OUTBOUND, NULL, m_username.empty() ? NULL : &id, NULL, NULL, &m_creds, &lifetime); MORDOR_LOG_TRACE(g_log) << "AcquireCredentialsHandleW(" << challenge.scheme << ", " << toUtf8(m_username) << "): (" << status << ")"; if (!SUCCEEDED(status)) MORDOR_THROW_EXCEPTION_FROM_ERROR_API(status, "AcquireCredentialsHandleW"); status = InitializeSecurityContextW( &m_creds, NULL, (wchar_t *)toUtf16(uri.toString()).c_str(), ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP, NULL, 0, &m_secCtx, &outboundBufferDesc, &contextAttributes, &lifetime); MORDOR_LOG_TRACE(g_log) << "InitializeSecurityContextW(" << uri << ", {0}): {" << outboundSecBuffer.cbBuffer << "} (" << status << ")"; } else { // Prepare the response from the server std::string inboundBuffer = base64decode(param); SecBufferDesc inboundBufferDesc; SecBuffer inboundSecBuffer; inboundBufferDesc.ulVersion = 0; inboundBufferDesc.cBuffers = 1; inboundBufferDesc.pBuffers = &inboundSecBuffer; inboundSecBuffer.BufferType = SECBUFFER_TOKEN; inboundSecBuffer.pvBuffer = &inboundBuffer[0]; inboundSecBuffer.cbBuffer = (unsigned long)inboundBuffer.size(); status = InitializeSecurityContextW( &m_creds, &m_secCtx, (wchar_t *)toUtf16(uri.toString()).c_str(), ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP, &inboundBufferDesc, 0, &m_secCtx, &outboundBufferDesc, &contextAttributes, &lifetime); MORDOR_LOG_TRACE(g_log) << "InitializeSecurityContextW(" << uri << ", {" << inboundSecBuffer.cbBuffer << "}): {" << outboundSecBuffer.cbBuffer << "} (" << status << ")"; } if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) { status = CompleteAuthToken(&m_secCtx, &outboundBufferDesc); MORDOR_LOG_TRACE(g_log) << "CompleteAuthToken(): {" << outboundSecBuffer.cbBuffer << "} (" << status << ")"; } if (!SUCCEEDED(status)) MORDOR_THROW_EXCEPTION_FROM_ERROR(status); outboundBuffer.resize(outboundSecBuffer.cbBuffer); authorization.scheme = challenge.scheme; authorization.base64 = base64encode(outboundBuffer); authorization.parameters.clear(); return true; }