secur32: Added support for SECPKG_ATTR_ENDPOINT_BINDINGS in schannel.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7966efda07
commit
0706ba1114
|
@ -23,6 +23,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winreg.h"
|
||||
|
@ -961,6 +962,23 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextA(
|
|||
return ret;
|
||||
}
|
||||
|
||||
static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx)
|
||||
{
|
||||
HCERTSTORE cert_store;
|
||||
SECURITY_STATUS status;
|
||||
|
||||
if(ctx->cert)
|
||||
return SEC_E_OK;
|
||||
|
||||
cert_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
if(!cert_store)
|
||||
return GetLastError();
|
||||
|
||||
status = schan_imp_get_session_peer_certificate(ctx->session, cert_store, &ctx->cert);
|
||||
CertCloseStore(cert_store, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
||||
PCtxtHandle context_handle, ULONG attribute, PVOID buffer)
|
||||
{
|
||||
|
@ -1001,20 +1019,11 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
|
||||
{
|
||||
PCCERT_CONTEXT *cert = buffer;
|
||||
SECURITY_STATUS status;
|
||||
|
||||
if (!ctx->cert) {
|
||||
HCERTSTORE cert_store;
|
||||
SECURITY_STATUS status;
|
||||
|
||||
cert_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
if(!cert_store)
|
||||
return GetLastError();
|
||||
|
||||
status = schan_imp_get_session_peer_certificate(ctx->session, cert_store, &ctx->cert);
|
||||
CertCloseStore(cert_store, 0);
|
||||
if(status != SEC_E_OK)
|
||||
return status;
|
||||
}
|
||||
status = ensure_remote_cert(ctx);
|
||||
if(status != SEC_E_OK)
|
||||
return status;
|
||||
|
||||
*cert = CertDuplicateCertificateContext(ctx->cert);
|
||||
return SEC_E_OK;
|
||||
|
@ -1024,6 +1033,47 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
SecPkgContext_ConnectionInfo *info = buffer;
|
||||
return schan_imp_get_connection_info(ctx->session, info);
|
||||
}
|
||||
case SECPKG_ATTR_ENDPOINT_BINDINGS:
|
||||
{
|
||||
SecPkgContext_Bindings *bindings = buffer;
|
||||
CCRYPT_OID_INFO *info;
|
||||
ALG_ID hash_alg = CALG_SHA_256;
|
||||
BYTE hash[1024];
|
||||
DWORD hash_size;
|
||||
SECURITY_STATUS status;
|
||||
char *p;
|
||||
BOOL r;
|
||||
|
||||
static const char prefix[] = "tls-server-end-point:";
|
||||
|
||||
status = ensure_remote_cert(ctx);
|
||||
if(status != SEC_E_OK)
|
||||
return status;
|
||||
|
||||
/* RFC 5929 */
|
||||
info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, ctx->cert->pCertInfo->SignatureAlgorithm.pszObjId, 0);
|
||||
if(info && info->u.Algid != CALG_SHA1 && info->u.Algid != CALG_MD5)
|
||||
hash_alg = info->u.Algid;
|
||||
|
||||
hash_size = sizeof(hash);
|
||||
r = CryptHashCertificate(0, hash_alg, 0, ctx->cert->pbCertEncoded, ctx->cert->cbCertEncoded, hash, &hash_size);
|
||||
if(!r)
|
||||
return GetLastError();
|
||||
|
||||
bindings->BindingsLength = sizeof(*bindings->Bindings) + sizeof(prefix)-1 + hash_size;
|
||||
bindings->Bindings = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bindings->BindingsLength);
|
||||
if(!bindings->Bindings)
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
|
||||
bindings->Bindings->cbApplicationDataLength = sizeof(prefix)-1 + hash_size;
|
||||
bindings->Bindings->dwApplicationDataOffset = sizeof(*bindings->Bindings);
|
||||
|
||||
p = (char*)(bindings->Bindings+1);
|
||||
memcpy(p, prefix, sizeof(prefix)-1);
|
||||
p += sizeof(prefix)-1;
|
||||
memcpy(p, hash, hash_size);
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
default:
|
||||
FIXME("Unhandled attribute %#x\n", attribute);
|
||||
|
@ -1045,6 +1095,8 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA(
|
|||
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
|
||||
case SECPKG_ATTR_CONNECTION_INFO:
|
||||
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
|
||||
case SECPKG_ATTR_ENDPOINT_BINDINGS:
|
||||
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
|
||||
|
||||
default:
|
||||
FIXME("Unhandled attribute %#x\n", attribute);
|
||||
|
|
|
@ -870,7 +870,49 @@ todo_wine
|
|||
status = pQueryContextAttributesA(&context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
|
||||
ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: %08x\n", status);
|
||||
if(status == SEC_E_OK) {
|
||||
SecPkgContext_Bindings bindings = {0xdeadbeef, (void*)0xdeadbeef};
|
||||
|
||||
test_remote_cert(cert);
|
||||
|
||||
status = pQueryContextAttributesA(&context, SECPKG_ATTR_ENDPOINT_BINDINGS, &bindings);
|
||||
ok(status == SEC_E_OK || broken(status == SEC_E_UNSUPPORTED_FUNCTION),
|
||||
"QueryContextAttributesW(SECPKG_ATTR_ENDPOINT_BINDINGS) failed: %08x\n", status);
|
||||
if(status == SEC_E_OK) {
|
||||
static const char prefix[] = "tls-server-end-point:";
|
||||
const char *p;
|
||||
BYTE hash[64];
|
||||
DWORD hash_size;
|
||||
|
||||
ok(bindings.BindingsLength == sizeof(*bindings.Bindings) + sizeof(prefix)-1 + 32 /* hash size */,
|
||||
"bindings.BindingsLength = %u\n", bindings.BindingsLength);
|
||||
ok(!bindings.Bindings->dwInitiatorAddrType, "dwInitiatorAddrType = %x\n", bindings.Bindings->dwInitiatorAddrType);
|
||||
ok(!bindings.Bindings->cbInitiatorLength, "cbInitiatorLength = %x\n", bindings.Bindings->cbInitiatorLength);
|
||||
ok(!bindings.Bindings->dwInitiatorOffset, "dwInitiatorOffset = %x\n", bindings.Bindings->dwInitiatorOffset);
|
||||
ok(!bindings.Bindings->dwAcceptorAddrType, "dwAcceptorAddrType = %x\n", bindings.Bindings->dwAcceptorAddrType);
|
||||
ok(!bindings.Bindings->cbAcceptorLength, "cbAcceptorLength = %x\n", bindings.Bindings->cbAcceptorLength);
|
||||
ok(!bindings.Bindings->dwAcceptorOffset, "dwAcceptorOffset = %x\n", bindings.Bindings->dwAcceptorOffset);
|
||||
ok(sizeof(*bindings.Bindings) + bindings.Bindings->cbApplicationDataLength == bindings.BindingsLength,
|
||||
"cbApplicationDataLength = %x\n", bindings.Bindings->cbApplicationDataLength);
|
||||
ok(bindings.Bindings->dwApplicationDataOffset == sizeof(*bindings.Bindings),
|
||||
"dwApplicationDataOffset = %x\n", bindings.Bindings->dwApplicationDataOffset);
|
||||
p = (const char*)(bindings.Bindings+1);
|
||||
ok(!memcmp(p, prefix, sizeof(prefix)-1), "missing prefix\n");
|
||||
p += sizeof(prefix)-1;
|
||||
|
||||
hash_size = sizeof(hash);
|
||||
ret = CryptHashCertificate(0, CALG_SHA_256, 0, cert->pbCertEncoded, cert->cbCertEncoded, hash, &hash_size);
|
||||
if(ret) {
|
||||
ok(hash_size == 32, "hash_size = %u\n", hash_size);
|
||||
ok(!memcmp(hash, p, hash_size), "unexpected hash part\n");
|
||||
}else {
|
||||
win_skip("SHA 256 hash not supported.\n");
|
||||
}
|
||||
|
||||
FreeContextBuffer(bindings.Bindings);
|
||||
}else {
|
||||
win_skip("SECPKG_ATTR_ENDPOINT_BINDINGS not supported\n");
|
||||
}
|
||||
|
||||
CertFreeCertificateContext(cert);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue