diff --git a/dlls/wininet/Makefile.in b/dlls/wininet/Makefile.in index 5b33c13cac5..e3ff75eaeec 100644 --- a/dlls/wininet/Makefile.in +++ b/dlls/wininet/Makefile.in @@ -6,6 +6,7 @@ VPATH = @srcdir@ MODULE = wininet.dll IMPORTLIB = libwininet.$(IMPLIBEXT) IMPORTS = mpr shlwapi shell32 user32 advapi32 kernel32 ntdll +DELAYIMPORTS = crypt32 EXTRALIBS = $(LIBUNICODE) @SOCKETLIBS@ C_SRCS = \ diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index dcc6f91b581..abb08251631 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -66,6 +66,7 @@ #include "resource.h" #include "wine/unicode.h" +#include "wincrypt.h" WINE_DEFAULT_DEBUG_CHANNEL(wininet); @@ -2242,6 +2243,41 @@ static BOOL INET_QueryOptionHelper(BOOL bIsUnicode, HINTERNET hInternet, DWORD d FIXME("INTERNET_OPTION_SECURITY_FLAGS: Stub\n"); break; + case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: + if (*lpdwBufferLength < sizeof(INTERNET_CERTIFICATE_INFOW)) + { + *lpdwBufferLength = sizeof(INTERNET_CERTIFICATE_INFOW); + INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + else if (lpwhh->htype == WH_HHTTPREQ) + { + LPWININETHTTPREQW lpwhr; + PCCERT_CONTEXT context; + + lpwhr = (LPWININETHTTPREQW)lpwhh; + context = (PCCERT_CONTEXT)NETCON_GetCert(&(lpwhr->netConnection)); + if (context) + { + LPINTERNET_CERTIFICATE_INFOW info = (LPINTERNET_CERTIFICATE_INFOW)lpBuffer; + memset(info,0,sizeof(INTERNET_CERTIFICATE_INFOW)); + info->ftExpiry = context->pCertInfo->NotAfter; + info->ftStart = context->pCertInfo->NotBefore; + /* + * CertNameToStr implement requred for + * lpszSubjectInfo + * lpszIssuerInfo + * + * also need to set: + * lpszProtocolName + * lpszSignatureAlgName + * lpszEncryptionAlgName + * dwKeySize + */ + CertFreeCertificateContext(context); + bSuccess = TRUE; + } + } + break; default: FIXME("Stub! %ld\n", dwOption); break; diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h index ab03236ce66..6df7e31d1a3 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -480,6 +480,7 @@ BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags, int *recvd /* out */); BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer); +LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection); extern void URLCacheContainers_CreateDefaults(void); extern void URLCacheContainers_DeleteAll(void); diff --git a/dlls/wininet/netconnection.c b/dlls/wininet/netconnection.c index f488d695b19..97608b68b02 100644 --- a/dlls/wininet/netconnection.c +++ b/dlls/wininet/netconnection.c @@ -52,6 +52,7 @@ #include "wine/debug.h" #include "internet.h" +#include "wincrypt.h" #define RESPONSE_TIMEOUT 30 /* FROM internet.c */ @@ -100,6 +101,7 @@ MAKE_FUNCPTR(SSL_get_peer_certificate); MAKE_FUNCPTR(SSL_CTX_get_timeout); MAKE_FUNCPTR(SSL_CTX_set_timeout); MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths); +MAKE_FUNCPTR(i2d_X509); /* OpenSSL's libcrypto functions that we use */ MAKE_FUNCPTR(BIO_new_fp); @@ -162,6 +164,7 @@ void NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) DYNSSL(SSL_CTX_get_timeout); DYNSSL(SSL_CTX_set_timeout); DYNSSL(SSL_CTX_set_default_verify_paths); + DYNSSL(i2d_X509); #undef DYNSSL #define DYNCRYPTO(x) \ @@ -658,3 +661,51 @@ BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPD #endif } } + + +LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection) +{ + +#if defined HAVE_OPENSSL_SSL_H && defined HAVE_OPENSSL_ERR_H + X509* cert; + unsigned char* buffer,*p; + INT len; + BOOL malloced = FALSE; + LPCVOID r = NULL; + + if (!connection->useSSL) + return NULL; + + cert = pSSL_get_peer_certificate(connection->ssl_s); + p = NULL; + len = pi2d_X509(cert,&p); + /* + * SSL 0.9.7 and above malloc the buffer if it is null. + * however earlier version do not and so we would need to alloc the buffer. + * + * see the i2d_X509 man page for more details. + */ + if (!p) + { + buffer = HeapAlloc(GetProcessHeap(),0,len); + p = buffer; + len = pi2d_X509(cert,&p); + } + else + { + buffer = p; + malloced = TRUE; + } + + r = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len); + + if (malloced) + free(buffer); + else + HeapFree(GetProcessHeap(),0,buffer); + + return r; +#else + return NULL; +#endif +}