From: Jacek Caban Subject: [PATCH 1/3] secur32: Return a cert context with context store in SECPKG_ATTR_REMOTE_CERT_CONTEXT GnuTLS implementation Message-Id: <50FD4AB8.7000700@codeweavers.com> Date: Mon, 21 Jan 2013 15:03:36 +0100 --- dlls/secur32/schannel.c | 13 ++++++++++++- dlls/secur32/schannel_gnutls.c | 30 ++++++++++++++++++------------ dlls/secur32/schannel_macosx.c | 2 +- dlls/secur32/secur32_priv.h | 2 +- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index cc287dc..37af15e 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -60,6 +60,7 @@ struct schan_context { schan_imp_session session; ULONG req_ctx_attr; + HCERTSTORE cert_store; }; static struct schan_handle *schan_handle_table; @@ -696,6 +697,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( ctx = HeapAlloc(GetProcessHeap(), 0, sizeof(*ctx)); if (!ctx) return SEC_E_INSUFFICIENT_MEMORY; + ctx->cert_store = NULL; handle = schan_alloc_handle(ctx, SCHAN_HANDLE_CTX); if (handle == SCHAN_INVALID_HANDLE) { @@ -859,7 +861,14 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_REMOTE_CERT_CONTEXT: { PCCERT_CONTEXT *cert = buffer; - return schan_imp_get_session_peer_certificate(ctx->session, cert); + + if (!ctx->cert_store) { + ctx->cert_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); + if(!ctx->cert_store) + return GetLastError(); + } + + return schan_imp_get_session_peer_certificate(ctx->session, ctx->cert_store, cert); } case SECPKG_ATTR_CONNECTION_INFO: { @@ -1167,6 +1176,8 @@ static SECURITY_STATUS SEC_ENTRY schan_DeleteSecurityContext(PCtxtHandle context ctx = schan_free_handle(context_handle->dwLower, SCHAN_HANDLE_CTX); if (!ctx) return SEC_E_INVALID_HANDLE; + if (ctx->cert_store) + CertCloseStore(ctx->cert_store, 0); schan_imp_dispose_session(ctx->session); HeapFree(GetProcessHeap(), 0, ctx); diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index bb481b7..fa68591 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -318,25 +318,31 @@ SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, return SEC_E_OK; } -SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, - PCCERT_CONTEXT *cert) +SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store, + PCCERT_CONTEXT *ret) { gnutls_session_t s = (gnutls_session_t)session; - unsigned int list_size; + PCCERT_CONTEXT cert = NULL; const gnutls_datum_t *datum; + unsigned list_size, i; + BOOL res; datum = pgnutls_certificate_get_peers(s, &list_size); - if (datum) - { - *cert = CertCreateCertificateContext(X509_ASN_ENCODING, datum->data, - datum->size); - if (!*cert) + if(!datum) + return SEC_E_INTERNAL_ERROR; + + for(i = 0; i < list_size; i++) { + res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, datum[i].data, datum[i].size, + CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert); + if(!res) { + if(i) + CertFreeCertificateContext(cert); return GetLastError(); - else - return SEC_E_OK; + } } - else - return SEC_E_INTERNAL_ERROR; + + *ret = cert; + return SEC_E_OK; } SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer, diff --git a/dlls/secur32/schannel_macosx.c b/dlls/secur32/schannel_macosx.c index 75fe9a0..2d03d2a 100644 --- a/dlls/secur32/schannel_macosx.c +++ b/dlls/secur32/schannel_macosx.c @@ -706,7 +706,7 @@ static void schan_imp_cf_release(const void *arg, void *ctx) } #endif -SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, +SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE cert_store, PCCERT_CONTEXT *cert) { struct mac_session* s = (struct mac_session*)session; diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 3254e0b..164a2eb 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -247,7 +247,7 @@ extern unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session se extern unsigned int schan_imp_get_max_message_size(schan_imp_session session) DECLSPEC_HIDDEN; extern SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, SecPkgContext_ConnectionInfo *info) DECLSPEC_HIDDEN; -extern SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, +extern SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE, PCCERT_CONTEXT *cert) DECLSPEC_HIDDEN; extern SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer, SIZE_T *length) DECLSPEC_HIDDEN;