From: Jacek Caban Subject: [PATCH 2/3] secur32: Return a cert context with context store in SECPKG_ATTR_REMOTE_CERT_CONTEXT MacOSX implementation Message-Id: <50FD4AC6.8080801@codeweavers.com> Date: Mon, 21 Jan 2013 15:03:50 +0100 --- dlls/secur32/schannel_macosx.c | 76 +++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/dlls/secur32/schannel_macosx.c b/dlls/secur32/schannel_macosx.c index 2d03d2a..aaf2532 100644 --- a/dlls/secur32/schannel_macosx.c +++ b/dlls/secur32/schannel_macosx.c @@ -706,53 +706,67 @@ static void schan_imp_cf_release(const void *arg, void *ctx) } #endif -SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE cert_store, - PCCERT_CONTEXT *cert) +SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store, + PCCERT_CONTEXT *ret_cert) { struct mac_session* s = (struct mac_session*)session; - SECURITY_STATUS ret = SEC_E_INTERNAL_ERROR; - CFArrayRef certs; + SECURITY_STATUS ret = SEC_E_OK; + PCCERT_CONTEXT cert = NULL; + SecCertificateRef mac_cert; + CFArrayRef cert_array; OSStatus status; + CFIndex cnt, i; + CFDataRef data; + BOOL res; TRACE("(%p/%p, %p)\n", s, s->context, cert); #ifdef HAVE_SSLCOPYPEERCERTIFICATES - status = SSLCopyPeerCertificates(s->context, &certs); + status = SSLCopyPeerCertificates(s->context, &cert_array); #else - status = SSLGetPeerCertificates(s->context, &certs); + status = SSLGetPeerCertificates(s->context, &cert_array); #endif - if (status == noErr && certs) + if (status != noErr || !cert_array) { - SecCertificateRef mac_cert; - CFDataRef data; - if (CFArrayGetCount(certs) && - (mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, 0)) && - (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) == noErr)) + WARN("SSLCopyPeerCertificates failed: %ld\n", (long)status); + return SEC_E_INTERNAL_ERROR; + } + + cnt = CFArrayGetCount(cert_array); + for (i=0; i < cnt; i++) { + if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) || + (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr)) { - *cert = CertCreateCertificateContext(X509_ASN_ENCODING, - CFDataGetBytePtr(data), CFDataGetLength(data)); - if (*cert) - ret = SEC_E_OK; - else - { - ret = GetLastError(); - WARN("CertCreateCertificateContext failed: %x\n", ret); - } - CFRelease(data); - } - else WARN("Couldn't extract certificate data\n"); + ret = SEC_E_INTERNAL_ERROR; + break; + } + + res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data), + CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert); + CFRelease(data); + if (!res) + { + ret = GetLastError(); + WARN("CertAddEncodedCertificateToStore failed: %x\n", ret); + break; + } + } + #ifndef HAVE_SSLCOPYPEERCERTIFICATES - /* This is why SSLGetPeerCertificates was deprecated */ - CFArrayApplyFunction(certs, CFRangeMake(0, CFArrayGetCount(certs)), - schan_imp_cf_release, NULL); + /* This is why SSLGetPeerCertificates was deprecated */ + CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)), + schan_imp_cf_release, NULL); #endif - CFRelease(certs); + CFRelease(cert_array); + if (ret != SEC_E_OK) { + if(cert) + CertFreeCertificateContext(cert); + return ret; } - else - WARN("SSLCopyPeerCertificates failed: %ld\n", (long)status); - return ret; + *ret_cert = cert; + return SEC_E_OK; } SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,