Module: wine Branch: master Commit: bcc30639ad6c61a15ac52979805af218502648ab URL: https://source.winehq.org/git/wine.git/?a=commit;h=bcc30639ad6c61a15ac529798...
Author: Alexandre Julliard julliard@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@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 *);