secur32: Add TLS application protocol negotiation support.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
86d20a47f4
commit
0527cf89fb
|
@ -786,6 +786,8 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
|
|||
struct schan_credentials *cred;
|
||||
SIZE_T expected_size = ~0UL;
|
||||
SECURITY_STATUS ret;
|
||||
SecBuffer *buffer;
|
||||
int idx;
|
||||
|
||||
TRACE("%p %p %s 0x%08x %d %d %p %d %p %p %p %p\n", phCredential, phContext,
|
||||
debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
|
||||
|
@ -842,6 +844,13 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
|
|||
heap_free( target );
|
||||
}
|
||||
}
|
||||
|
||||
if (pInput && (idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_APPLICATION_PROTOCOLS)) != -1)
|
||||
{
|
||||
buffer = &pInput->pBuffers[idx];
|
||||
schan_imp_set_application_protocols(ctx->session, buffer->pvBuffer, buffer->cbBuffer);
|
||||
}
|
||||
|
||||
phNewContext->dwLower = handle;
|
||||
phNewContext->dwUpper = 0;
|
||||
}
|
||||
|
@ -849,8 +858,6 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
|
|||
{
|
||||
SIZE_T record_size = 0;
|
||||
unsigned char *ptr;
|
||||
SecBuffer *buffer;
|
||||
int idx;
|
||||
|
||||
if (!pInput)
|
||||
return SEC_E_INCOMPLETE_MESSAGE;
|
||||
|
@ -1003,6 +1010,7 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
PCtxtHandle context_handle, ULONG attribute, PVOID buffer)
|
||||
{
|
||||
struct schan_context *ctx;
|
||||
SECURITY_STATUS status;
|
||||
|
||||
TRACE("context_handle %p, attribute %#x, buffer %p\n",
|
||||
context_handle, attribute, buffer);
|
||||
|
@ -1015,7 +1023,7 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
case SECPKG_ATTR_STREAM_SIZES:
|
||||
{
|
||||
SecPkgContext_ConnectionInfo info;
|
||||
SECURITY_STATUS status = schan_imp_get_connection_info(ctx->session, &info);
|
||||
status = schan_imp_get_connection_info(ctx->session, &info);
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
SecPkgContext_StreamSizes *stream_sizes = buffer;
|
||||
|
@ -1039,7 +1047,7 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
case SECPKG_ATTR_KEY_INFO:
|
||||
{
|
||||
SecPkgContext_ConnectionInfo conn_info;
|
||||
SECURITY_STATUS status = schan_imp_get_connection_info(ctx->session, &conn_info);
|
||||
status = schan_imp_get_connection_info(ctx->session, &conn_info);
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
SecPkgContext_KeyInfoW *info = buffer;
|
||||
|
@ -1054,7 +1062,6 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
|
||||
{
|
||||
PCCERT_CONTEXT *cert = buffer;
|
||||
SECURITY_STATUS status;
|
||||
|
||||
status = ensure_remote_cert(ctx);
|
||||
if(status != SEC_E_OK)
|
||||
|
@ -1075,7 +1082,6 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
ALG_ID hash_alg = CALG_SHA_256;
|
||||
BYTE hash[1024];
|
||||
DWORD hash_size;
|
||||
SECURITY_STATUS status;
|
||||
char *p;
|
||||
BOOL r;
|
||||
|
||||
|
@ -1109,6 +1115,11 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
|
|||
memcpy(p, hash, hash_size);
|
||||
return SEC_E_OK;
|
||||
}
|
||||
case SECPKG_ATTR_APPLICATION_PROTOCOL:
|
||||
{
|
||||
SecPkgContext_ApplicationProtocol *protocol = buffer;
|
||||
return schan_imp_get_application_protocol(ctx->session, protocol);
|
||||
}
|
||||
|
||||
default:
|
||||
FIXME("Unhandled attribute %#x\n", attribute);
|
||||
|
@ -1143,6 +1154,8 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA(
|
|||
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
|
||||
case SECPKG_ATTR_ENDPOINT_BINDINGS:
|
||||
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
|
||||
case SECPKG_ATTR_APPLICATION_PROTOCOL:
|
||||
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
|
||||
|
||||
default:
|
||||
FIXME("Unhandled attribute %#x\n", attribute);
|
||||
|
|
|
@ -50,6 +50,11 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
|||
/* Not present in gnutls version < 2.9.10. */
|
||||
static int (*pgnutls_cipher_get_block_size)(gnutls_cipher_algorithm_t);
|
||||
|
||||
/* Not present in gnutls version < 3.2.0. */
|
||||
static int (*pgnutls_alpn_get_selected_protocol)(gnutls_session_t, gnutls_datum_t *);
|
||||
static int (*pgnutls_alpn_set_protocols)(gnutls_session_t, const gnutls_datum_t *,
|
||||
unsigned, unsigned int);
|
||||
|
||||
/* Not present in gnutls version < 3.3.0. */
|
||||
static int (*pgnutls_privkey_import_rsa_raw)(gnutls_privkey_t, const gnutls_datum_t *,
|
||||
const gnutls_datum_t *, const gnutls_datum_t *,
|
||||
|
@ -114,6 +119,10 @@ MAKE_FUNCPTR(gnutls_x509_privkey_deinit);
|
|||
#define GNUTLS_KX_ECDHE_PSK 14
|
||||
#endif
|
||||
|
||||
#if GNUTLS_VERSION_MAJOR < 3 || (GNUTLS_VERSION_MAJOR == 3 && GNUTLS_VERSION_MINOR < 2)
|
||||
#define GNUTLS_ALPN_SERVER_PRECEDENCE (1<<1)
|
||||
#endif
|
||||
|
||||
static int compat_cipher_get_block_size(gnutls_cipher_algorithm_t cipher)
|
||||
{
|
||||
switch(cipher) {
|
||||
|
@ -153,6 +162,19 @@ static int compat_gnutls_privkey_import_rsa_raw(gnutls_privkey_t key, const gnut
|
|||
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
|
||||
}
|
||||
|
||||
static int compat_gnutls_alpn_get_selected_protocol(gnutls_session_t session, gnutls_datum_t *protocol)
|
||||
{
|
||||
FIXME("\n");
|
||||
return GNUTLS_E_INVALID_REQUEST;
|
||||
}
|
||||
|
||||
static int compat_gnutls_alpn_set_protocols(gnutls_session_t session, const gnutls_datum_t *protocols,
|
||||
unsigned size, unsigned int flags)
|
||||
{
|
||||
FIXME("\n");
|
||||
return GNUTLS_E_INVALID_REQUEST;
|
||||
}
|
||||
|
||||
static ssize_t schan_pull_adapter(gnutls_transport_ptr_t transport,
|
||||
void *buff, size_t buff_len)
|
||||
{
|
||||
|
@ -599,6 +621,86 @@ again:
|
|||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
static unsigned int parse_alpn_protocol_list(unsigned char *buffer, unsigned int buflen, gnutls_datum_t *list)
|
||||
{
|
||||
unsigned int len, offset = 0, count = 0;
|
||||
|
||||
while (buflen)
|
||||
{
|
||||
len = buffer[offset++];
|
||||
buflen--;
|
||||
if (!len || len > buflen) return 0;
|
||||
if (list)
|
||||
{
|
||||
list[count].data = &buffer[offset];
|
||||
list[count].size = len;
|
||||
}
|
||||
buflen -= len;
|
||||
offset += len;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void schan_imp_set_application_protocols(schan_imp_session session, unsigned char *buffer, unsigned int buflen)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
unsigned int extension_len, extension, count = 0, offset = 0;
|
||||
unsigned short list_len;
|
||||
gnutls_datum_t *protocols;
|
||||
int ret;
|
||||
|
||||
if (sizeof(extension_len) > buflen) return;
|
||||
extension_len = *(unsigned int *)&buffer[offset];
|
||||
offset += sizeof(extension_len);
|
||||
|
||||
if (offset + sizeof(extension) > buflen) return;
|
||||
extension = *(unsigned int *)&buffer[offset];
|
||||
if (extension != SecApplicationProtocolNegotiationExt_ALPN)
|
||||
{
|
||||
FIXME("extension %u not supported\n", extension);
|
||||
return;
|
||||
}
|
||||
offset += sizeof(extension);
|
||||
|
||||
if (offset + sizeof(list_len) > buflen) return;
|
||||
list_len = *(unsigned short *)&buffer[offset];
|
||||
offset += sizeof(list_len);
|
||||
|
||||
if (offset + list_len > buflen) return;
|
||||
count = parse_alpn_protocol_list(&buffer[offset], list_len, NULL);
|
||||
if (!count || !(protocols = heap_alloc(count * sizeof(*protocols)))) return;
|
||||
|
||||
parse_alpn_protocol_list(&buffer[offset], list_len, protocols);
|
||||
if ((ret = pgnutls_alpn_set_protocols(s, protocols, count, GNUTLS_ALPN_SERVER_PRECEDENCE) < 0))
|
||||
{
|
||||
pgnutls_perror(ret);
|
||||
}
|
||||
|
||||
heap_free(protocols);
|
||||
}
|
||||
|
||||
SECURITY_STATUS schan_imp_get_application_protocol(schan_imp_session session,
|
||||
SecPkgContext_ApplicationProtocol *protocol)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
gnutls_datum_t selected;
|
||||
|
||||
memset(protocol, 0, sizeof(*protocol));
|
||||
if (pgnutls_alpn_get_selected_protocol(s, &selected) < 0) return SEC_E_OK;
|
||||
|
||||
if (selected.size <= sizeof(protocol->ProtocolId))
|
||||
{
|
||||
protocol->ProtoNegoStatus = SecApplicationProtocolNegotiationStatus_Success;
|
||||
protocol->ProtoNegoExt = SecApplicationProtocolNegotiationExt_ALPN;
|
||||
protocol->ProtocolIdSize = selected.size;
|
||||
memcpy(protocol->ProtocolId, selected.data, selected.size);
|
||||
TRACE("returning %s\n", debugstr_an((const char *)selected.data, selected.size));
|
||||
}
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
static WCHAR *get_key_container_path(const CERT_CONTEXT *ctx)
|
||||
{
|
||||
static const WCHAR rsabaseW[] =
|
||||
|
@ -935,6 +1037,16 @@ BOOL schan_imp_init(void)
|
|||
WARN("gnutls_cipher_get_block_size not found\n");
|
||||
pgnutls_cipher_get_block_size = compat_cipher_get_block_size;
|
||||
}
|
||||
if (!(pgnutls_alpn_set_protocols = dlsym(libgnutls_handle, "gnutls_alpn_set_protocols")))
|
||||
{
|
||||
WARN("gnutls_alpn_set_protocols not found\n");
|
||||
pgnutls_alpn_set_protocols = compat_gnutls_alpn_set_protocols;
|
||||
}
|
||||
if (!(pgnutls_alpn_get_selected_protocol = dlsym(libgnutls_handle, "gnutls_alpn_get_selected_protocol")))
|
||||
{
|
||||
WARN("gnutls_alpn_get_selected_protocol not found\n");
|
||||
pgnutls_alpn_get_selected_protocol = compat_gnutls_alpn_get_selected_protocol;
|
||||
}
|
||||
if (!(pgnutls_privkey_export_x509 = dlsym(libgnutls_handle, "gnutls_privkey_export_x509")))
|
||||
{
|
||||
WARN("gnutls_privkey_export_x509 not found\n");
|
||||
|
|
|
@ -248,6 +248,8 @@ extern void schan_imp_free_certificate_credentials(schan_credentials*) DECLSPEC_
|
|||
extern DWORD schan_imp_enabled_protocols(void) DECLSPEC_HIDDEN;
|
||||
extern BOOL schan_imp_init(void) DECLSPEC_HIDDEN;
|
||||
extern void schan_imp_deinit(void) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void schan_imp_set_application_protocols(schan_imp_session, unsigned char *, unsigned int) DECLSPEC_HIDDEN;
|
||||
extern SECURITY_STATUS schan_imp_get_application_protocol(schan_imp_session,
|
||||
SecPkgContext_ApplicationProtocol *) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* ndef __SECUR32_PRIV_H__ */
|
||||
|
|
|
@ -670,14 +670,41 @@ static void test_InitializeSecurityContext(void)
|
|||
FreeCredentialsHandle(&cred_handle);
|
||||
}
|
||||
|
||||
static SOCKET create_ssl_socket( const char *hostname )
|
||||
{
|
||||
struct hostent *host;
|
||||
struct sockaddr_in addr;
|
||||
SOCKET sock;
|
||||
|
||||
if (!(host = gethostbyname(hostname)))
|
||||
{
|
||||
skip("Can't resolve \"%s\"\n", hostname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sin_family = host->h_addrtype;
|
||||
addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
|
||||
addr.sin_port = htons(443);
|
||||
if ((sock = socket(host->h_addrtype, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
skip("Can't create socket\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
skip("Can't connect to \"%s\"\n", hostname);
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
static void test_communication(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WSADATA wsa_data;
|
||||
SOCKET sock;
|
||||
struct hostent *host;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
SECURITY_STATUS status;
|
||||
ULONG attrs;
|
||||
|
@ -705,36 +732,7 @@ static void test_communication(void)
|
|||
}
|
||||
|
||||
/* Create a socket and connect to test.winehq.org */
|
||||
ret = WSAStartup(0x0202, &wsa_data);
|
||||
if (ret)
|
||||
{
|
||||
skip("Can't init winsock 2.2\n");
|
||||
return;
|
||||
}
|
||||
|
||||
host = gethostbyname("test.winehq.org");
|
||||
if (!host)
|
||||
{
|
||||
skip("Can't resolve test.winehq.org\n");
|
||||
return;
|
||||
}
|
||||
|
||||
addr.sin_family = host->h_addrtype;
|
||||
addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
|
||||
addr.sin_port = htons(443);
|
||||
sock = socket(host->h_addrtype, SOCK_STREAM, 0);
|
||||
if (sock == SOCKET_ERROR)
|
||||
{
|
||||
skip("Can't create socket\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (ret == SOCKET_ERROR)
|
||||
{
|
||||
skip("Can't connect to test.winehq.org\n");
|
||||
return;
|
||||
}
|
||||
if ((sock = create_ssl_socket( "test.winehq.org" )) == -1) return;
|
||||
|
||||
/* Create client credentials */
|
||||
init_cred(&cred);
|
||||
|
@ -952,7 +950,7 @@ todo_wine
|
|||
status = pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
|
||||
ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_STREAM_SIZES) failed: %08x\n", status);
|
||||
|
||||
status = QueryContextAttributesA(&context, SECPKG_ATTR_NEGOTIATION_INFO, &info);
|
||||
status = pQueryContextAttributesA(&context, SECPKG_ATTR_NEGOTIATION_INFO, &info);
|
||||
ok(status == SEC_E_UNSUPPORTED_FUNCTION, "QueryContextAttributesA returned %08x\n", status);
|
||||
|
||||
reset_buffers(&buffers[0]);
|
||||
|
@ -1037,12 +1035,142 @@ todo_wine
|
|||
closesocket(sock);
|
||||
}
|
||||
|
||||
static void test_application_protocol_negotiation(void)
|
||||
{
|
||||
int ret;
|
||||
SOCKET sock;
|
||||
SECURITY_STATUS status;
|
||||
ULONG attrs;
|
||||
SCHANNEL_CRED cred;
|
||||
CredHandle cred_handle;
|
||||
CtxtHandle context;
|
||||
SecPkgContext_ApplicationProtocol protocol;
|
||||
SecBufferDesc buffers[3];
|
||||
SecBuffer *buf;
|
||||
unsigned buf_size = 8192;
|
||||
unsigned char *alpn_buffer;
|
||||
unsigned int *extension_len;
|
||||
unsigned short *list_len;
|
||||
int list_start_index, offset = 0;
|
||||
|
||||
if (!pQueryContextAttributesA)
|
||||
{
|
||||
win_skip("Required secur32 functions not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sock = create_ssl_socket( "test.winehq.org" )) == -1) return;
|
||||
|
||||
init_cred(&cred);
|
||||
cred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;
|
||||
cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||
|
||||
status = AcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
|
||||
&cred, NULL, NULL, &cred_handle, NULL);
|
||||
ok(status == SEC_E_OK, "got %08x\n", status);
|
||||
if (status != SEC_E_OK) return;
|
||||
|
||||
init_buffers(&buffers[0], 4, buf_size);
|
||||
init_buffers(&buffers[1], 4, buf_size);
|
||||
init_buffers(&buffers[2], 1, 128);
|
||||
|
||||
alpn_buffer = buffers[2].pBuffers[0].pvBuffer;
|
||||
extension_len = (unsigned int *)&alpn_buffer[offset];
|
||||
offset += sizeof(*extension_len);
|
||||
*(unsigned int *)&alpn_buffer[offset] = SecApplicationProtocolNegotiationExt_ALPN;
|
||||
offset += sizeof(unsigned int);
|
||||
list_len = (unsigned short *)&alpn_buffer[offset];
|
||||
offset += sizeof(*list_len);
|
||||
list_start_index = offset;
|
||||
|
||||
alpn_buffer[offset++] = sizeof("http/1.1") - 1;
|
||||
memcpy(&alpn_buffer[offset], "http/1.1", sizeof("http/1.1") - 1);
|
||||
offset += sizeof("http/1.1") - 1;
|
||||
alpn_buffer[offset++] = sizeof("h2") - 1;
|
||||
memcpy(&alpn_buffer[offset], "h2", sizeof("h2") - 1);
|
||||
offset += sizeof("h2") - 1;
|
||||
|
||||
*list_len = offset - list_start_index;
|
||||
*extension_len = *list_len + sizeof(*extension_len) + sizeof(*list_len);
|
||||
|
||||
buffers[2].pBuffers[0].BufferType = SECBUFFER_APPLICATION_PROTOCOLS;
|
||||
buffers[2].pBuffers[0].cbBuffer = offset;
|
||||
|
||||
buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
|
||||
status = InitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
|
||||
ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM, 0, 0, &buffers[2], 0, &context, &buffers[0], &attrs, NULL);
|
||||
ok(status == SEC_I_CONTINUE_NEEDED, "got %08x\n", status);
|
||||
|
||||
buf = &buffers[0].pBuffers[0];
|
||||
send(sock, buf->pvBuffer, buf->cbBuffer, 0);
|
||||
buf->cbBuffer = buf_size;
|
||||
|
||||
buf = &buffers[1].pBuffers[0];
|
||||
buf->cbBuffer = buf_size;
|
||||
ret = receive_data(sock, buf);
|
||||
if (ret == -1)
|
||||
return;
|
||||
|
||||
buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
|
||||
status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
|
||||
ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM|ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, &buffers[1], 0, NULL,
|
||||
&buffers[0], &attrs, NULL);
|
||||
buffers[1].pBuffers[0].cbBuffer = buf_size;
|
||||
while (status == SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
buf = &buffers[0].pBuffers[0];
|
||||
send(sock, buf->pvBuffer, buf->cbBuffer, 0);
|
||||
buf->cbBuffer = buf_size;
|
||||
|
||||
buf = &buffers[1].pBuffers[0];
|
||||
ret = receive_data(sock, buf);
|
||||
if (ret == -1)
|
||||
return;
|
||||
|
||||
buf->BufferType = SECBUFFER_TOKEN;
|
||||
status = InitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
|
||||
ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
|
||||
buffers[1].pBuffers[0].cbBuffer = buf_size;
|
||||
}
|
||||
|
||||
ok (status == SEC_E_OK || broken(status == SEC_E_ILLEGAL_MESSAGE) /* winxp */, "got %08x\n", status);
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
skip("Handshake failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&protocol, 0, sizeof(protocol));
|
||||
status = pQueryContextAttributesA(&context, SECPKG_ATTR_APPLICATION_PROTOCOL, &protocol);
|
||||
ok(status == SEC_E_OK || broken(status == SEC_E_UNSUPPORTED_FUNCTION) /* win2k8 */, "got %08x\n", status);
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
ok(protocol.ProtoNegoStatus == SecApplicationProtocolNegotiationStatus_Success, "got %u\n", protocol.ProtoNegoStatus);
|
||||
ok(protocol.ProtoNegoExt == SecApplicationProtocolNegotiationExt_ALPN, "got %u\n", protocol.ProtoNegoExt);
|
||||
ok(protocol.ProtocolIdSize == 8, "got %u\n", protocol.ProtocolIdSize);
|
||||
ok(!memcmp(protocol.ProtocolId, "http/1.1", 8), "wrong protocol id\n");
|
||||
}
|
||||
|
||||
DeleteSecurityContext(&context);
|
||||
FreeCredentialsHandle(&cred_handle);
|
||||
|
||||
free_buffers(&buffers[0]);
|
||||
free_buffers(&buffers[1]);
|
||||
free_buffers(&buffers[2]);
|
||||
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
START_TEST(schannel)
|
||||
{
|
||||
WSADATA wsa_data;
|
||||
pQueryContextAttributesA = (void*)GetProcAddress(GetModuleHandleA("secur32.dll"), "QueryContextAttributesA");
|
||||
|
||||
WSAStartup(0x0202, &wsa_data);
|
||||
|
||||
test_cread_attrs();
|
||||
testAcquireSecurityContext();
|
||||
test_InitializeSecurityContext();
|
||||
test_communication();
|
||||
test_application_protocol_negotiation();
|
||||
}
|
||||
|
|
|
@ -201,6 +201,7 @@ typedef struct _SecBuffer
|
|||
#define SECBUFFER_MECHLIST_SIGNATURE 12
|
||||
#define SECBUFFER_TARGET 13
|
||||
#define SECBUFFER_CHANNEL_BINDINGS 14
|
||||
#define SECBUFFER_APPLICATION_PROTOCOLS 18
|
||||
|
||||
#define SECBUFFER_ATTRMASK 0xf0000000
|
||||
#define SECBUFFER_READONLY 0x80000000
|
||||
|
@ -497,6 +498,7 @@ typedef SECURITY_STATUS (SEC_ENTRY *QUERY_CONTEXT_ATTRIBUTES_FN_W)(PCtxtHandle,
|
|||
#define SECPKG_ATTR_NEGO_PKG_INFO 31
|
||||
#define SECPKG_ATTR_NEGO_STATUS 32
|
||||
#define SECPKG_ATTR_CONTEXT_DELETED 33
|
||||
#define SECPKG_ATTR_APPLICATION_PROTOCOL 35
|
||||
|
||||
#define SECPKG_ATTR_SUBJECT_SECURITY_ATTRIBUTES 128
|
||||
#define SECPKG_ATTR_NEGO_INFO_FLAG_NO_KERBEROS 0x1
|
||||
|
@ -712,6 +714,30 @@ typedef struct _SecPkgContext_Bindings
|
|||
SEC_CHANNEL_BINDINGS *Bindings;
|
||||
} SecPkgContext_Bindings, *PSecPkgContext_Bindings;
|
||||
|
||||
typedef enum _SEC_APPLICATION_PROTOCOL_NEGOTIATION_STATUS
|
||||
{
|
||||
SecApplicationProtocolNegotiationStatus_None,
|
||||
SecApplicationProtocolNegotiationStatus_Success,
|
||||
SecApplicationProtocolNegotiationStatus_SelectedClientOnly
|
||||
} SEC_APPLICATION_PROTOCOL_NEGOTIATION_STATUS, *PSEC_APPLICATION_PROTOCOL_NEGOTIATION_STATUS;
|
||||
|
||||
typedef enum _SEC_APPLICATION_PROTOCOL_NEGOTIATION_EXT
|
||||
{
|
||||
SecApplicationProtocolNegotiationExt_None,
|
||||
SecApplicationProtocolNegotiationExt_NPN,
|
||||
SecApplicationProtocolNegotiationExt_ALPN
|
||||
} SEC_APPLICATION_PROTOCOL_NEGOTIATION_EXT, *PSEC_APPLICATION_PROTOCOL_NEGOTIATION_EXT;
|
||||
|
||||
#define MAX_PROTOCOL_ID_SIZE 0xff
|
||||
|
||||
typedef struct _SecPkgContext_ApplicationProtocol
|
||||
{
|
||||
SEC_APPLICATION_PROTOCOL_NEGOTIATION_STATUS ProtoNegoStatus;
|
||||
SEC_APPLICATION_PROTOCOL_NEGOTIATION_EXT ProtoNegoExt;
|
||||
unsigned char ProtocolIdSize;
|
||||
unsigned char ProtocolId[MAX_PROTOCOL_ID_SIZE];
|
||||
} SecPkgContext_ApplicationProtocol, *PSecPkgContext_ApplicationProtocol;
|
||||
|
||||
SECURITY_STATUS SEC_ENTRY ImpersonateSecurityContext(PCtxtHandle phContext);
|
||||
|
||||
typedef SECURITY_STATUS (SEC_ENTRY *IMPERSONATE_SECURITY_CONTEXT_FN)
|
||||
|
|
Loading…
Reference in New Issue