Use single buffer for returned certificate blobs, instead of an array of CERT_BLOB that contains pointers.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 18 +++++++++++------- dlls/secur32/schannel_gnutls.c | 14 +++++++------- dlls/secur32/secur32_priv.h | 2 +- 3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 6ab5507becf..2e663872f71 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -1026,7 +1026,6 @@ static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx) HCERTSTORE store; PCCERT_CONTEXT cert = NULL; SECURITY_STATUS status; - CERT_BLOB *certs; ULONG count, size = 0; struct get_session_peer_certificate_params params = { ctx->transport.session, NULL, &size, &count };
@@ -1036,28 +1035,33 @@ static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx)
status = GNUTLS_CALL( get_session_peer_certificate, ¶ms ); if (status != SEC_E_BUFFER_TOO_SMALL) goto done; - if (!(certs = malloc( size ))) + if (!(params.buffer = malloc( size ))) { status = SEC_E_INSUFFICIENT_MEMORY; goto done; } - params.certs = certs; status = GNUTLS_CALL( get_session_peer_certificate, ¶ms ); if (status == SEC_E_OK) { unsigned int i; + ULONG *sizes; + BYTE *blob; + + sizes = (ULONG *)params.buffer; + blob = params.buffer + count * sizeof(*sizes); + for (i = 0; i < count; i++) { - if (!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, certs[i].pbData, - certs[i].cbData, CERT_STORE_ADD_REPLACE_EXISTING, - i ? NULL : &cert)) + if (!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, blob, sizes[i], + CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert)) { if (i) CertFreeCertificateContext(cert); return GetLastError(); } + blob += sizes[i]; } } - free(certs); + free(params.buffer); done: ctx->cert = cert; CertCloseStore(store, 0); diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 0145c59e0f0..7c6a0bc0cfc 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -792,28 +792,28 @@ static NTSTATUS schan_get_session_peer_certificate( void *args ) { const struct get_session_peer_certificate_params *params = args; gnutls_session_t s = (gnutls_session_t)params->session; - CERT_BLOB *certs = params->certs; const gnutls_datum_t *datum; unsigned int i, size; BYTE *ptr; unsigned int count; + ULONG *sizes;
if (!(datum = pgnutls_certificate_get_peers(s, &count))) return SEC_E_INTERNAL_ERROR;
- size = count * sizeof(certs[0]); + size = count * sizeof(*sizes); for (i = 0; i < count; i++) size += datum[i].size;
- if (!certs || *params->bufsize < size) + if (!params->buffer || *params->bufsize < size) { *params->bufsize = size; return SEC_E_BUFFER_TOO_SMALL; } - ptr = (BYTE *)&certs[count]; + sizes = (ULONG *)params->buffer; + ptr = params->buffer + count * sizeof(*sizes); 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); + sizes[i] = datum[i].size; + memcpy(ptr, datum[i].data, datum[i].size); ptr += datum[i].size; }
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index be375618266..5c35e4244c8 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -145,7 +145,7 @@ struct get_connection_info_params struct get_session_peer_certificate_params { schan_session session; - CERT_BLOB *certs; + BYTE *buffer; /* Starts with array of ULONG sizes, followed by contiguous data blob. */ ULONG *bufsize; ULONG *retcount; };