NegotiateAuth::~NegotiateAuth() { if (SecIsValidHandle(&m_creds)) { FreeCredentialHandle(&m_creds); SecInvalidateHandle(&m_creds); } if (SecIsValidHandle(&m_secCtx)) { FreeCredentialHandle(&m_secCtx); SecInvalidateHandle(&m_secCtx); } }
/* Cleans the SSPI context object, when the pool used to create it gets cleared or destroyed. */ static apr_status_t cleanup_ctx(void *data) { serf__kerb_context_t *ctx = data; if (SecIsValidHandle(&ctx->sspi_context)) { DeleteSecurityContext(&ctx->sspi_context); SecInvalidateHandle(&ctx->sspi_context); } if (SecIsValidHandle(&ctx->sspi_credentials)) { FreeCredentialsHandle(&ctx->sspi_context); SecInvalidateHandle(&ctx->sspi_context); } return APR_SUCCESS; }
void UnloadSslModule(void) { if (g_pSSPI && SecIsValidHandle(&hCreds)) g_pSSPI->FreeCredentialsHandle(&hCreds); CloseHandle(g_hSslMutex); if (g_hSchannel) FreeLibrary(g_hSchannel); }
SslCredential::~SslCredential() { if (SecIsValidHandle(&credHandle)) ::FreeCredentialsHandle(&credHandle); if (cert) ::CertFreeCertificateContext(cert); if (certStore) ::CertCloseStore(certStore, CERT_CLOSE_STORE_FORCE_FLAG); }
void* sspi_SecureHandleGetUpperPointer(SecHandle* handle) { void* pointer; if (!handle || !SecIsValidHandle(handle) || !handle->dwUpper) return NULL; pointer = (void*) ~((size_t) handle->dwUpper); return pointer; }
RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) { TRACE("(Connection == ^%p)\n", Connection); if (SecIsValidHandle(&Connection->ctx)) { DeleteSecurityContext(&Connection->ctx); SecInvalidateHandle(&Connection->ctx); } rpcrt4_conn_close(Connection); return RPC_S_OK; }
apr_status_t serf__kerb_reset_sec_context(serf__kerb_context_t *ctx) { if (SecIsValidHandle(&ctx->sspi_context)) { DeleteSecurityContext(&ctx->sspi_context); SecInvalidateHandle(&ctx->sspi_context); } ctx->initalized = FALSE; return APR_SUCCESS; }
static bool ClientConnect(SslHandle *ssl, const char *host) { if (SecIsValidHandle(&ssl->hContext)) { g_pSSPI->DeleteSecurityContext(&ssl->hContext); SecInvalidateHandle(&ssl->hContext); } if (MySslEmptyCache) MySslEmptyCache(); DWORD dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; // Initiate a ClientHello message and generate a token. SecBuffer OutBuffers[1]; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; SecBufferDesc OutBuffer; OutBuffer.cBuffers = _countof(OutBuffers); OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; TimeStamp tsExpiry; DWORD dwSSPIOutFlags; SECURITY_STATUS scRet = g_pSSPI->InitializeSecurityContext(&hCreds, NULL, _A2T(host), dwSSPIFlags, 0, 0, NULL, 0, &ssl->hContext, &OutBuffer, &dwSSPIOutFlags, &tsExpiry); if (scRet != SEC_I_CONTINUE_NEEDED) { ReportSslError(scRet, __LINE__); return 0; } // Send response to server if there is one. if (OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL) { DWORD cbData = send(ssl->s, (char*)OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0); if (cbData == SOCKET_ERROR || cbData == 0) { Netlib_Logf(NULL, "SSL failure sending connection data (%d %d)", ssl->s, WSAGetLastError()); g_pSSPI->FreeContextBuffer(OutBuffers[0].pvBuffer); return 0; } // Free output buffer. g_pSSPI->FreeContextBuffer(OutBuffers[0].pvBuffer); OutBuffers[0].pvBuffer = NULL; } return ClientHandshakeLoop(ssl, TRUE) == SEC_E_OK; }
void NetlibDestroySecurityProvider(HANDLE hSecurity) { if (hSecurity == NULL) return; mir_cslock lck(csSec); if (ntlmCnt != 0) { NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; if (hNtlm != NULL) { if (SecIsValidHandle(&hNtlm->hClientContext)) DeleteSecurityContext(&hNtlm->hClientContext); if (SecIsValidHandle(&hNtlm->hClientCredential)) FreeCredentialsHandle(&hNtlm->hClientCredential); mir_free(hNtlm->szProvider); mir_free(hNtlm->szPrincipal); mir_free(hNtlm); } --ntlmCnt; } }
void NetlibSslShutdown(SslHandle *ssl) { if (ssl == NULL || !SecIsValidHandle(&ssl->hContext)) return; DWORD dwType = SCHANNEL_SHUTDOWN; SecBuffer OutBuffers[1]; OutBuffers[0].pvBuffer = &dwType; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = sizeof(dwType); SecBufferDesc OutBuffer; OutBuffer.cBuffers = _countof(OutBuffers); OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; SECURITY_STATUS scRet = g_pSSPI->ApplyControlToken(&ssl->hContext, &OutBuffer); if (FAILED(scRet)) return; // Build an SSL close notify message. DWORD dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; OutBuffer.cBuffers = 1; OutBuffer.pBuffers = OutBuffers; OutBuffer.ulVersion = SECBUFFER_VERSION; TimeStamp tsExpiry; DWORD dwSSPIOutFlags; scRet = g_pSSPI->InitializeSecurityContext(&hCreds, &ssl->hContext, NULL, dwSSPIFlags, 0, 0, NULL, 0, &ssl->hContext, &OutBuffer, &dwSSPIOutFlags, &tsExpiry); if (FAILED(scRet)) return; // Send the close notify message to the server. if (OutBuffers[0].pvBuffer != NULL && OutBuffers[0].cbBuffer != 0) { send(ssl->s, (char*)OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0); g_pSSPI->FreeContextBuffer(OutBuffers[0].pvBuffer); } }
void NetlibDestroySecurityProvider(HANDLE hSecurity) { if (hSecurity == NULL) return; WaitForSingleObject(hSecMutex, INFINITE); if (ntlmCnt != 0) { NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; if (SecIsValidHandle(&hNtlm->hClientContext)) g_pSSPI->DeleteSecurityContext(&hNtlm->hClientContext); if (SecIsValidHandle(&hNtlm->hClientCredential)) g_pSSPI->FreeCredentialsHandle(&hNtlm->hClientCredential); mir_free(hNtlm->szProvider); mir_free(hNtlm->szPrincipal); --ntlmCnt; mir_free(hNtlm); } if (secCnt && --secCnt == 0) FreeSecurityLibrary(); ReleaseMutex(hSecMutex); }
void free_netconn(netconn_t *netconn) { server_release(netconn->server); if (netconn->secure) { heap_free(netconn->peek_msg_mem); netconn->peek_msg_mem = NULL; netconn->peek_msg = NULL; netconn->peek_len = 0; heap_free(netconn->ssl_buf); netconn->ssl_buf = NULL; heap_free(netconn->extra_buf); netconn->extra_buf = NULL; netconn->extra_len = 0; if (SecIsValidHandle(&netconn->ssl_ctx)) DeleteSecurityContext(&netconn->ssl_ctx); } heap_free(netconn); }
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; }
char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge, const TCHAR* login, const TCHAR* psw, bool http, unsigned& complete) { SECURITY_STATUS sc; SecBufferDesc outputBufferDescriptor,inputBufferDescriptor; SecBuffer outputSecurityToken,inputSecurityToken; TimeStamp tokenExpiration; ULONG contextAttributes; NETLIBBASE64 nlb64 = { 0 }; NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; if (hSecurity == NULL || ntlmCnt == 0) return NULL; if (_tcsicmp(hNtlm->szProvider, _T("Basic"))) { bool isGSSAPI = _tcsicmp(hNtlm->szProvider, _T("GSSAPI")) == 0; TCHAR *szProvider = isGSSAPI ? _T("Kerberos") : hNtlm->szProvider; bool hasChallenge = szChallenge != NULL && szChallenge[0] != '\0'; if (hasChallenge) { nlb64.cchEncoded = lstrlenA(szChallenge); nlb64.pszEncoded = (char*)szChallenge; nlb64.cbDecoded = Netlib_GetBase64DecodedBufferSize(nlb64.cchEncoded); nlb64.pbDecoded = (PBYTE)alloca(nlb64.cbDecoded); if (!NetlibBase64Decode(0, (LPARAM)&nlb64)) return NULL; if (isGSSAPI && complete) return CompleteGssapi(hSecurity, nlb64.pbDecoded, nlb64.cbDecoded); inputBufferDescriptor.cBuffers = 1; inputBufferDescriptor.pBuffers = &inputSecurityToken; inputBufferDescriptor.ulVersion = SECBUFFER_VERSION; inputSecurityToken.BufferType = SECBUFFER_TOKEN; inputSecurityToken.cbBuffer = nlb64.cbDecoded; inputSecurityToken.pvBuffer = nlb64.pbDecoded; // try to decode the domain name from the NTLM challenge if (login != NULL && login[0] != '\0' && !hNtlm->hasDomain) { NtlmType2packet* pkt = ( NtlmType2packet* )nlb64.pbDecoded; if (!strncmp(pkt->sign, "NTLMSSP", 8) && pkt->type == 2) { #ifdef UNICODE wchar_t* domainName = (wchar_t*)&nlb64.pbDecoded[pkt->targetName.offset]; int domainLen = pkt->targetName.len; // Negotiate ANSI? if yes, convert the ANSI name to unicode if ((pkt->flags & 1) == 0) { int bufsz = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, NULL, 0); wchar_t* buf = (wchar_t*)alloca(bufsz * sizeof(wchar_t)); domainLen = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, buf, bufsz) - 1; domainName = buf; } else domainLen /= sizeof(wchar_t); #else char* domainName = (char*)&nlb64.pbDecoded[pkt->targetName.offset]; int domainLen = pkt->targetName.len; // Negotiate Unicode? if yes, convert the unicode name to ANSI if (pkt->flags & 1) { int bufsz = WideCharToMultiByte(CP_ACP, 0, (WCHAR*)domainName, domainLen, NULL, 0, NULL, NULL); char* buf = (char*)alloca(bufsz); domainLen = WideCharToMultiByte(CP_ACP, 0, (WCHAR*)domainName, domainLen, buf, bufsz, NULL, NULL) - 1; domainName = buf; } #endif if (domainLen) { size_t newLoginLen = _tcslen(login) + domainLen + 1; TCHAR *newLogin = (TCHAR*)alloca(newLoginLen * sizeof(TCHAR)); _tcsncpy(newLogin, domainName, domainLen); newLogin[domainLen] = '\\'; _tcscpy(newLogin + domainLen + 1, login); char* szChl = NtlmCreateResponseFromChallenge(hSecurity, NULL, newLogin, psw, http, complete); mir_free(szChl); } } } } else { if (SecIsValidHandle(&hNtlm->hClientContext)) g_pSSPI->DeleteSecurityContext(&hNtlm->hClientContext); if (SecIsValidHandle(&hNtlm->hClientCredential)) g_pSSPI->FreeCredentialsHandle(&hNtlm->hClientCredential); SEC_WINNT_AUTH_IDENTITY auth; if (login != NULL && login[0] != '\0') { memset(&auth, 0, sizeof(auth)); #ifdef _UNICODE NetlibLogf(NULL, "Security login requested, user: %S pssw: %s", login, psw ? "(exist)" : "(no psw)"); #else NetlibLogf(NULL, "Security login requested, user: %s pssw: %s", login, psw ? "(exist)" : "(no psw)"); #endif const TCHAR* loginName = login; const TCHAR* domainName = _tcschr(login, '\\'); int domainLen = 0; int loginLen = lstrlen(loginName); if (domainName != NULL) { loginName = domainName + 1; loginLen = lstrlen(loginName); domainLen = domainName - login; domainName = login; } else if ((domainName = _tcschr(login, '@')) != NULL) { loginName = login; loginLen = domainName - login; domainLen = lstrlen(++domainName); } #ifdef UNICODE auth.User = (PWORD)loginName; auth.UserLength = loginLen; auth.Password = (PWORD)psw; auth.PasswordLength = lstrlen(psw); auth.Domain = (PWORD)domainName; auth.DomainLength = domainLen; auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; #else auth.User = (PBYTE)loginName; auth.UserLength = loginLen; auth.Password = (PBYTE)psw; auth.PasswordLength = lstrlen(psw); auth.Domain = (PBYTE)domainName; auth.DomainLength = domainLen; auth.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; #endif hNtlm->hasDomain = domainLen != 0; } sc = g_pSSPI->AcquireCredentialsHandle(NULL, szProvider, SECPKG_CRED_OUTBOUND, NULL, hNtlm->hasDomain ? &auth : NULL, NULL, NULL, &hNtlm->hClientCredential, &tokenExpiration); if (sc != SEC_E_OK) { ReportSecError(sc, __LINE__); return NULL; } } outputBufferDescriptor.cBuffers = 1; outputBufferDescriptor.pBuffers = &outputSecurityToken; outputBufferDescriptor.ulVersion = SECBUFFER_VERSION; outputSecurityToken.BufferType = SECBUFFER_TOKEN; outputSecurityToken.cbBuffer = hNtlm->cbMaxToken; outputSecurityToken.pvBuffer = alloca(outputSecurityToken.cbBuffer); sc = g_pSSPI->InitializeSecurityContext(&hNtlm->hClientCredential, hasChallenge ? &hNtlm->hClientContext : NULL, hNtlm->szPrincipal, isGSSAPI ? ISC_REQ_MUTUAL_AUTH | ISC_REQ_STREAM : 0, 0, SECURITY_NATIVE_DREP, hasChallenge ? &inputBufferDescriptor : NULL, 0, &hNtlm->hClientContext, &outputBufferDescriptor, &contextAttributes, &tokenExpiration); complete = (sc != SEC_I_COMPLETE_AND_CONTINUE && sc != SEC_I_CONTINUE_NEEDED); if (sc == SEC_I_COMPLETE_NEEDED || sc == SEC_I_COMPLETE_AND_CONTINUE) { sc = g_pSSPI->CompleteAuthToken(&hNtlm->hClientContext, &outputBufferDescriptor); } if (sc != SEC_E_OK && sc != SEC_I_CONTINUE_NEEDED) { ReportSecError(sc, __LINE__); return NULL; } nlb64.cbDecoded = outputSecurityToken.cbBuffer; nlb64.pbDecoded = (PBYTE)outputSecurityToken.pvBuffer; } else { if (!login || !psw) return NULL; char *szLogin = mir_t2a(login); char *szPassw = mir_t2a(psw); size_t authLen = strlen(szLogin) + strlen(szPassw) + 5; char *szAuth = (char*)alloca(authLen); nlb64.cbDecoded = mir_snprintf(szAuth, authLen,"%s:%s", szLogin, szPassw); nlb64.pbDecoded=(PBYTE)szAuth; complete = true; mir_free(szPassw); mir_free(szLogin); } nlb64.cchEncoded = Netlib_GetBase64EncodedBufferSize(nlb64.cbDecoded); nlb64.pszEncoded = (char*)alloca(nlb64.cchEncoded); if (!NetlibBase64Encode(0,(LPARAM)&nlb64)) return NULL; char* result; if (http) { char* szProvider = mir_t2a(hNtlm->szProvider); nlb64.cchEncoded += (int)strlen(szProvider) + 10; result = (char*)mir_alloc(nlb64.cchEncoded); mir_snprintf(result, nlb64.cchEncoded, "%s %s", szProvider, nlb64.pszEncoded); mir_free(szProvider); } else result = mir_strdup(nlb64.pszEncoded); return result; }
char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge, const TCHAR* login, const TCHAR* psw, bool http, unsigned& complete) { if (hSecurity == NULL || ntlmCnt == 0) return NULL; SecBufferDesc outputBufferDescriptor, inputBufferDescriptor; SecBuffer outputSecurityToken, inputSecurityToken; TimeStamp tokenExpiration; ULONG contextAttributes; char *szOutputToken; NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; if (mir_tstrcmpi(hNtlm->szProvider, _T("Basic"))) { bool isGSSAPI = mir_tstrcmpi(hNtlm->szProvider, _T("GSSAPI")) == 0; TCHAR *szProvider = isGSSAPI ? (TCHAR*)_T("Kerberos") : hNtlm->szProvider; bool hasChallenge = szChallenge != NULL && szChallenge[0] != '\0'; if (hasChallenge) { unsigned tokenLen; BYTE *token = (BYTE*)mir_base64_decode(szChallenge, &tokenLen); if (token == NULL) return NULL; if (isGSSAPI && complete) return CompleteGssapi(hSecurity, token, tokenLen); inputBufferDescriptor.cBuffers = 1; inputBufferDescriptor.pBuffers = &inputSecurityToken; inputBufferDescriptor.ulVersion = SECBUFFER_VERSION; inputSecurityToken.BufferType = SECBUFFER_TOKEN; inputSecurityToken.cbBuffer = tokenLen; inputSecurityToken.pvBuffer = token; // try to decode the domain name from the NTLM challenge if (login != NULL && login[0] != '\0' && !hNtlm->hasDomain) { NtlmType2packet* pkt = (NtlmType2packet*)token; if (!strncmp(pkt->sign, "NTLMSSP", 8) && pkt->type == 2) { wchar_t* domainName = (wchar_t*)&token[pkt->targetName.offset]; int domainLen = pkt->targetName.len; // Negotiate ANSI? if yes, convert the ANSI name to unicode if ((pkt->flags & 1) == 0) { int bufsz = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, NULL, 0); wchar_t* buf = (wchar_t*)alloca(bufsz * sizeof(wchar_t)); domainLen = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, buf, bufsz) - 1; domainName = buf; } else domainLen /= sizeof(wchar_t); if (domainLen) { size_t newLoginLen = mir_tstrlen(login) + domainLen + 1; TCHAR *newLogin = (TCHAR*)alloca(newLoginLen * sizeof(TCHAR)); _tcsncpy(newLogin, domainName, domainLen); newLogin[domainLen] = '\\'; mir_tstrcpy(newLogin + domainLen + 1, login); char* szChl = NtlmCreateResponseFromChallenge(hSecurity, NULL, newLogin, psw, http, complete); mir_free(szChl); } } } } else { if (SecIsValidHandle(&hNtlm->hClientContext)) DeleteSecurityContext(&hNtlm->hClientContext); if (SecIsValidHandle(&hNtlm->hClientCredential)) FreeCredentialsHandle(&hNtlm->hClientCredential); SEC_WINNT_AUTH_IDENTITY auth; if (login != NULL && login[0] != '\0') { memset(&auth, 0, sizeof(auth)); NetlibLogf(NULL, "Security login requested, user: %S pssw: %s", login, psw ? "(exist)" : "(no psw)"); const TCHAR* loginName = login; const TCHAR* domainName = _tcschr(login, '\\'); size_t domainLen = 0; size_t loginLen = mir_tstrlen(loginName); if (domainName != NULL) { loginName = domainName + 1; loginLen = mir_tstrlen(loginName); domainLen = domainName - login; domainName = login; } else if ((domainName = _tcschr(login, '@')) != NULL) { loginName = login; loginLen = domainName - login; domainLen = mir_tstrlen(++domainName); } auth.User = (PWORD)loginName; auth.UserLength = (ULONG)loginLen; auth.Password = (PWORD)psw; auth.PasswordLength = (ULONG)mir_tstrlen(psw); auth.Domain = (PWORD)domainName; auth.DomainLength = (ULONG)domainLen; auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; hNtlm->hasDomain = domainLen != 0; } SECURITY_STATUS sc = AcquireCredentialsHandle(NULL, szProvider, SECPKG_CRED_OUTBOUND, NULL, hNtlm->hasDomain ? &auth : NULL, NULL, NULL, &hNtlm->hClientCredential, &tokenExpiration); if (sc != SEC_E_OK) { ReportSecError(sc, __LINE__); return NULL; } } outputBufferDescriptor.cBuffers = 1; outputBufferDescriptor.pBuffers = &outputSecurityToken; outputBufferDescriptor.ulVersion = SECBUFFER_VERSION; outputSecurityToken.BufferType = SECBUFFER_TOKEN; outputSecurityToken.cbBuffer = hNtlm->cbMaxToken; outputSecurityToken.pvBuffer = alloca(outputSecurityToken.cbBuffer); SECURITY_STATUS sc = InitializeSecurityContext(&hNtlm->hClientCredential, hasChallenge ? &hNtlm->hClientContext : NULL, hNtlm->szPrincipal, isGSSAPI ? ISC_REQ_MUTUAL_AUTH | ISC_REQ_STREAM : 0, 0, SECURITY_NATIVE_DREP, hasChallenge ? &inputBufferDescriptor : NULL, 0, &hNtlm->hClientContext, &outputBufferDescriptor, &contextAttributes, &tokenExpiration); complete = (sc != SEC_I_COMPLETE_AND_CONTINUE && sc != SEC_I_CONTINUE_NEEDED); if (sc == SEC_I_COMPLETE_NEEDED || sc == SEC_I_COMPLETE_AND_CONTINUE) sc = CompleteAuthToken(&hNtlm->hClientContext, &outputBufferDescriptor); if (sc != SEC_E_OK && sc != SEC_I_CONTINUE_NEEDED) { ReportSecError(sc, __LINE__); return NULL; } szOutputToken = mir_base64_encode((PBYTE)outputSecurityToken.pvBuffer, outputSecurityToken.cbBuffer); } else { if (!login || !psw) return NULL; char *szLogin = mir_t2a(login); char *szPassw = mir_t2a(psw); size_t authLen = mir_strlen(szLogin) + mir_strlen(szPassw) + 5; char *szAuth = (char*)alloca(authLen); int len = mir_snprintf(szAuth, authLen, "%s:%s", szLogin, szPassw); szOutputToken = mir_base64_encode((BYTE*)szAuth, len); complete = true; mir_free(szPassw); mir_free(szLogin); } if (szOutputToken == NULL) return NULL; if (!http) return szOutputToken; ptrA szProvider(mir_t2a(hNtlm->szProvider)); size_t resLen = mir_strlen(szOutputToken) + mir_strlen(szProvider) + 10; char *result = (char*)mir_alloc(resLen); mir_snprintf(result, resLen, "%s %s", szProvider, szOutputToken); mir_free(szOutputToken); return result; }
static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode) { SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}}; SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs}; SecHandle *cred = &cred_handle; BYTE *read_buf; SIZE_T read_buf_size = 2048; ULONG attrs = 0; CtxtHandle ctx; SSIZE_T size; int bits; const CERT_CONTEXT *cert; SECURITY_STATUS status; DWORD res = ERROR_SUCCESS; const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION; if(!ensure_cred_handle()) return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; if(compat_mode) { if(!have_compat_cred_handle) return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; cred = &compat_cred_handle; } read_buf = heap_alloc(read_buf_size); if(!read_buf) return ERROR_OUTOFMEMORY; status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0, &ctx, &out_desc, &attrs, NULL); assert(status != SEC_E_OK); while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) { if(out_buf.cbBuffer) { assert(status == SEC_I_CONTINUE_NEEDED); TRACE("sending %lu bytes\n", out_buf.cbBuffer); size = sock_send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0); if(size != out_buf.cbBuffer) { ERR("send failed\n"); status = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; break; } FreeContextBuffer(out_buf.pvBuffer); out_buf.pvBuffer = NULL; out_buf.cbBuffer = 0; } if(status == SEC_I_CONTINUE_NEEDED) { assert(in_bufs[1].cbBuffer < read_buf_size); memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer); in_bufs[0].cbBuffer = in_bufs[1].cbBuffer; in_bufs[1].BufferType = SECBUFFER_EMPTY; in_bufs[1].cbBuffer = 0; in_bufs[1].pvBuffer = NULL; } assert(in_bufs[0].BufferType == SECBUFFER_TOKEN); assert(in_bufs[1].BufferType == SECBUFFER_EMPTY); if(in_bufs[0].cbBuffer + 1024 > read_buf_size) { BYTE *new_read_buf; new_read_buf = heap_realloc(read_buf, read_buf_size + 1024); if(!new_read_buf) { status = E_OUTOFMEMORY; break; } in_bufs[0].pvBuffer = read_buf = new_read_buf; read_buf_size += 1024; } size = sock_recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0); if(size < 1) { WARN("recv error\n"); res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; break; } TRACE("recv %tu bytes\n", size); in_bufs[0].cbBuffer += size; in_bufs[0].pvBuffer = read_buf; status = InitializeSecurityContextW(cred, &ctx, connection->server->name, isc_req_flags, 0, 0, &in_desc, 0, NULL, &out_desc, &attrs, NULL); TRACE("InitializeSecurityContext ret %08x\n", status); if(status == SEC_E_OK) { if(SecIsValidHandle(&connection->ssl_ctx)) DeleteSecurityContext(&connection->ssl_ctx); connection->ssl_ctx = ctx; if(in_bufs[1].BufferType == SECBUFFER_EXTRA) FIXME("SECBUFFER_EXTRA not supported\n"); status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &connection->ssl_sizes); if(status != SEC_E_OK) { WARN("Could not get sizes\n"); break; } status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert); if(status == SEC_E_OK) { res = netconn_verify_cert(connection, cert, cert->hCertStore); CertFreeCertificateContext(cert); if(res != ERROR_SUCCESS) { WARN("cert verify failed: %u\n", res); break; } }else { WARN("Could not get cert\n"); break; } connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage + connection->ssl_sizes.cbTrailer); if(!connection->ssl_buf) { res = GetLastError(); break; } } } heap_free(read_buf); if(status != SEC_E_OK || res != ERROR_SUCCESS) { WARN("Failed to establish SSL connection: %08x (%u)\n", status, res); heap_free(connection->ssl_buf); connection->ssl_buf = NULL; return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR; } TRACE("established SSL connection\n"); connection->secure = TRUE; connection->security_flags |= SECURITY_FLAG_SECURE; bits = NETCON_GetCipherStrength(connection); if (bits >= 128) connection->security_flags |= SECURITY_FLAG_STRENGTH_STRONG; else if (bits >= 56) connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM; else connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK; if(connection->mask_errors) connection->server->security_flags = connection->security_flags; return ERROR_SUCCESS; }
bool isValid() const { return SecIsValidHandle(&contextHandle_); }