Alexandre Julliard : secur32: Move the memory allocation for get_session_peer_certificate() to the PE side.
Alexandre Julliard
julliard at winehq.org
Mon Dec 6 16:07:58 CST 2021
Module: wine
Branch: master
Commit: bcc30639ad6c61a15ac52979805af218502648ab
URL: https://source.winehq.org/git/wine.git/?a=commit;h=bcc30639ad6c61a15ac52979805af218502648ab
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Dec 3 14:31:38 2021 +0100
secur32: Move the memory allocation for get_session_peer_certificate() to the PE side.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/secur32/schannel.c | 23 ++++++++++++++++-------
dlls/secur32/schannel_gnutls.c | 28 ++++++++++++++++++----------
dlls/secur32/secur32_priv.h | 8 +-------
3 files changed, 35 insertions(+), 24 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index f9deb5d8a23..483e3285f09 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -909,28 +909,37 @@ static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx)
HCERTSTORE store;
PCCERT_CONTEXT cert = NULL;
SECURITY_STATUS status;
- struct schan_cert_list list;
+ CERT_BLOB *certs;
+ ULONG count, size = 0;
if (ctx->cert) return SEC_E_OK;
if (!(store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL)))
return GetLastError();
- if ((status = schan_funcs->get_session_peer_certificate(ctx->transport.session, &list)) == SEC_E_OK)
+ status = schan_funcs->get_session_peer_certificate(ctx->transport.session, NULL, &size, &count);
+ if (status != SEC_E_BUFFER_TOO_SMALL) goto done;
+ if (!(certs = malloc( size )))
+ {
+ status = SEC_E_INSUFFICIENT_MEMORY;
+ goto done;
+ }
+ status = schan_funcs->get_session_peer_certificate(ctx->transport.session, certs, &size, &count);
+ if (status == SEC_E_OK)
{
unsigned int i;
- for (i = 0; i < list.count; i++)
+ for (i = 0; i < count; i++)
{
- if (!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, list.certs[i].pbData,
- list.certs[i].cbData, CERT_STORE_ADD_REPLACE_EXISTING,
+ if (!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, certs[i].pbData,
+ certs[i].cbData, CERT_STORE_ADD_REPLACE_EXISTING,
i ? NULL : &cert))
{
if (i) CertFreeCertificateContext(cert);
return GetLastError();
}
}
- RtlFreeHeap(GetProcessHeap(), 0, list.certs);
}
-
+ free(certs);
+done:
ctx->cert = cert;
CertCloseStore(store, 0);
return status;
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c
index 8a540035bdc..392d10e538b 100644
--- a/dlls/secur32/schannel_gnutls.c
+++ b/dlls/secur32/schannel_gnutls.c
@@ -810,28 +810,36 @@ static ALG_ID CDECL schan_get_key_signature_algorithm(schan_session session)
}
}
-static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session session, struct schan_cert_list *list)
+static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session session, CERT_BLOB *certs,
+ ULONG *bufsize, ULONG *retcount)
{
gnutls_session_t s = (gnutls_session_t)session;
const gnutls_datum_t *datum;
unsigned int i, size;
BYTE *ptr;
+ unsigned int count;
- if (!(datum = pgnutls_certificate_get_peers(s, &list->count))) return SEC_E_INTERNAL_ERROR;
+ if (!(datum = pgnutls_certificate_get_peers(s, &count))) return SEC_E_INTERNAL_ERROR;
- size = list->count * sizeof(list->certs[0]);
- for (i = 0; i < list->count; i++) size += datum[i].size;
- if (!(list->certs = RtlAllocateHeap(GetProcessHeap(), 0, size))) return SEC_E_INSUFFICIENT_MEMORY;
+ size = count * sizeof(certs[0]);
+ for (i = 0; i < count; i++) size += datum[i].size;
- ptr = (BYTE *)&list->certs[list->count];
- for (i = 0; i < list->count; i++)
+ if (!certs || *bufsize < size)
{
- list->certs[i].cbData = datum[i].size;
- list->certs[i].pbData = ptr;
- memcpy(list->certs[i].pbData, datum[i].data, datum[i].size);
+ *bufsize = size;
+ return SEC_E_BUFFER_TOO_SMALL;
+ }
+ ptr = (BYTE *)&certs[count];
+ for (i = 0; i < count; i++)
+ {
+ certs[i].cbData = datum[i].size;
+ certs[i].pbData = ptr;
+ memcpy(certs[i].pbData, datum[i].data, datum[i].size);
ptr += datum[i].size;
}
+ *bufsize = size;
+ *retcount = count;
return SEC_E_OK;
}
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h
index 3552a6aaf38..7cad59a51f7 100644
--- a/dlls/secur32/secur32_priv.h
+++ b/dlls/secur32/secur32_priv.h
@@ -108,12 +108,6 @@ struct schan_transport
struct schan_buffers out;
};
-struct schan_cert_list
-{
- unsigned int count;
- CERT_BLOB *certs;
-};
-
struct schan_funcs
{
BOOL (CDECL *allocate_certificate_credentials)(schan_credentials *, const CERT_CONTEXT *, const DATA_BLOB *);
@@ -126,7 +120,7 @@ struct schan_funcs
ALG_ID (CDECL *get_key_signature_algorithm)(schan_session);
unsigned int (CDECL *get_max_message_size)(schan_session);
unsigned int (CDECL *get_session_cipher_block_size)(schan_session);
- SECURITY_STATUS (CDECL *get_session_peer_certificate)(schan_session, struct schan_cert_list *);
+ SECURITY_STATUS (CDECL *get_session_peer_certificate)(schan_session, CERT_BLOB *, ULONG *, ULONG *);
SECURITY_STATUS (CDECL *get_unique_channel_binding)(schan_session, SecPkgContext_Bindings *);
SECURITY_STATUS (CDECL *handshake)(schan_session, SecBufferDesc *, SIZE_T, SecBufferDesc *, ULONG );
SECURITY_STATUS (CDECL *recv)(schan_session, SecBufferDesc *, SIZE_T, void *, SIZE_T *);
More information about the wine-cvs
mailing list