Any ideas?
In Python for instance, that's very simple:
Code: Select all
import ssl
ssl.get_server_certificate(('server.test.com', 443))
Code: Select all
import ssl
ssl.get_server_certificate(('server.test.com', 443))
Code: Select all
PCCERT_CHAIN_CONTEXT CertCtx=NULL;
DWORD cbCertSize = sizeof(&CertCtx);
//GetCertificate information
if (InternetQueryOption(hReq,INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT ,(LPVOID)&CertCtx,&cbCertSize))
{
//---------------------------------------------------------------
// Display some of the contents of the chain.
PCCERT_CHAIN_CONTEXT pChainContext=CertCtx;
printf("The size of the chain context is %d. \n",pChainContext->cbSize);
printf("%d simple chains found.\n",pChainContext->cChain);
printf("\nError status for the chain:\n");
CERT_SIMPLE_CHAIN *simpleCertificateChainWithinContext = NULL;
for (int i=0; i<pChainContext->cChain; i++)
{
simpleCertificateChainWithinContext=pChainContext->rgpChain[i];
// for each certificate chain in this context...
for (int simpleCertChainIndex = 0;
simpleCertChainIndex < simpleCertificateChainWithinContext->cElement;
simpleCertChainIndex++)
{
// get the CertContext from the array
PCCERT_CONTEXT pCertContext =
simpleCertificateChainWithinContext->rgpElement[simpleCertChainIndex]->pCertContext;
//-------------------------------------------------------------------
// Find and print the name of the subject of the certificate
// just retrieved.
TCHAR pszNameString[256];
if(CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
128))
{
wprintf(L"Certificate for %s has been retrieved.\n", pszNameString);
}
else
{
wprintf(L"CertGetName failed. \n");
}
// Get the issuer now...
if(CertGetNameString( pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
pszNameString,
128))
{
wprintf(L"Certificate issuer is %s.\n\n", pszNameString);
}
else
{
wprintf(L"CertGetName failed. \n");
}
}
}
//important! Free the CertCtx
CertFreeCertificateChain(CertCtx);
}
else
{
ErrorOut (GetLastError(), TEXT("HttpQueryInfo"));
}
Code: Select all
#INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105
#CERT_NAME_SIMPLE_DISPLAY_TYPE = 4
#CERT_NAME_ISSUER_FLAG = $00000001
...
Code: Select all
#INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105
#CERT_NAME_SIMPLE_DISPLAY_TYPE = 4
#CERT_NAME_ISSUER_FLAG = $00000001
Structure CERT_CONTEXT
dwCertEncodingType.l
*pbCertEncoded.Byte
cbCertEncoded.l
*CertInfo.CERT_INFO
HCERTSTORE.l
EndStructure
Structure CERT_TRUST_STATUS
dwErrorStatus.l
dwInfoStatus.l
EndStructure
Structure CERT_CHAIN_ELEMENT
cbSize.l
*CertContext.CERT_CONTEXT
TrustStatus.CERT_TRUST_STATUS
*RevocationInfo.CERT_REVOCATION_INFO
*IssuanceUsage.CERT_ENHKEY_USAGE
*ApplicationUsage.CERT_ENHKEY_USAGE
*ExtendedErrorInfo
EndStructure
Structure CERT_SIMPLE_CHAIN
cbSize.l
TrustStatus.CERT_TRUST_STATUS
cElement.l
*rgpElement.CERT_CHAIN_ELEMENT[0]
*TrustListInfo.CERT_TRUST_LIST_INFO
fHasRevocationFreshnessTime.i
dwRevocationFreshnessTime.l
EndStructure
Structure CERT_CHAIN_CONTEXT
cbSize.l
TrustStatus.CERT_TRUST_STATUS
cChain.l
*rgpChain.CERT_SIMPLE_CHAIN[0]
cLowerQualityChainContext.l
*rgpLowerQualityChainContext.CERT_CHAIN_CONTEXT
fHasRevocationFreshnessTime.i
dwRevocationFreshnessTime.l
dwCreateFlags.l
ChainId.GUID
EndStructure
Define cbCertSize.l = SizeOf(CERT_CHAIN_CONTEXT);
Define *CertCtx.CERT_CHAIN_CONTEXT
Define *ChainContext.CERT_CHAIN_CONTEXT
Define *simpleCertificateChainWithinContext.CERT_SIMPLE_CHAIN
Define *CertContext.CERT_CONTEXT
Define i.i, simpleCertChainIndex.i
file$ = "https://ipinfo.io/8.8.8.8/org"
#INTERNET_FLAG_RELOAD = $80000000
#INTERNET_OPTION_SECURITY_FLAGS = 31
#SECURITY_FLAG_IGNORE_UNKNOWN_CA = $100
Bytes.l = 0
Html.s = Space(50000)
hInet.l = InternetOpen_("", 0, #Null, #Null, 0)
dwFlags.l = 0
dwBuffLen = SizeOf(dwFlags)
dwFlags = $2000|$1000|$200|$100 ; $800000| |$80
InternetSetOption_(hInet, #INTERNET_OPTION_SECURITY_FLAGS, @dwFlags, SizeOf(dwFlags))
hURL.l = InternetOpenUrl_(hInet, file$, #Null, 0, #INTERNET_FLAG_RELOAD, 0)
InternetReadFile_(hURL, @Html, Len(Html), @Bytes)
html = PeekS(@HTML, Len(HTML), #PB_Ascii)
Debug "HTML: " + html
;
Debug hInet
*CertCtx = AllocateMemory(cbCertSize)
InternetQueryOption_(hInet, #INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT , @*CertCtx, @cbCertSize)
Debug "The size of the chain context is " + Str(*CertCtx\cbSize)
Code: Select all
EnableExplicit
#INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105
#CERT_NAME_SIMPLE_DISPLAY_TYPE = 4
#CERT_NAME_ISSUER_FLAG = $00000001
...
Code: Select all
EnableExplicit
#INTERNET_FLAG_RELOAD = $80000000
#INTERNET_OPTION_SECURITY_FLAGS = 31
#INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105
#SECURITY_FLAG_IGNORE_UNKNOWN_CA = $100
#CERT_NAME_SIMPLE_DISPLAY_TYPE = 4
#CERT_NAME_ISSUER_FLAG = $00000001
Structure CERT_CONTEXT Align #PB_Structure_AlignC
dwCertEncodingType.l
*pbCertEncoded.Byte
cbCertEncoded.l
*CertInfo.CERT_INFO
HCERTSTORE.l
EndStructure
Structure CERT_TRUST_STATUS Align #PB_Structure_AlignC
dwErrorStatus.l
dwInfoStatus.l
EndStructure
Structure CERT_CHAIN_ELEMENT Align #PB_Structure_AlignC
cbSize.l
*CertContext.CERT_CONTEXT
TrustStatus.CERT_TRUST_STATUS
*RevocationInfo.CERT_REVOCATION_INFO
*IssuanceUsage.CERT_ENHKEY_USAGE
*ApplicationUsage.CERT_ENHKEY_USAGE
*ExtendedErrorInfo
EndStructure
Structure CERT_SIMPLE_CHAIN Align #PB_Structure_AlignC
cbSize.l
TrustStatus.CERT_TRUST_STATUS
cElement.l
*rgpElement.CERT_CHAIN_ELEMENT[0]
*TrustListInfo.CERT_TRUST_LIST_INFO
fHasRevocationFreshnessTime.l
dwRevocationFreshnessTime.l
EndStructure
Structure CERT_CHAIN_CONTEXT Align #PB_Structure_AlignC
cbSize.l
TrustStatus.CERT_TRUST_STATUS
cChain.l
*rgpChain.CERT_SIMPLE_CHAIN[0]
cLowerQualityChainContext.l
*rgpLowerQualityChainContext.CERT_CHAIN_CONTEXT
fHasRevocationFreshnessTime.l
dwRevocationFreshnessTime.l
dwCreateFlags.l
ChainId.GUID
EndStructure
Define *CertCtx.CERT_CHAIN_CONTEXT
Define *ChainContext.CERT_CHAIN_CONTEXT
Define *simpleCertificateChainWithinContext.CERT_SIMPLE_CHAIN
Define *CertContext.CERT_CONTEXT
Define.i i, simpleCertChainIndex
Define.l Bytes, hInet, dwFlags, hConnect, hRequest, dwContext, cbCertSize
Define *SimpleChain.CERT_CHAIN_ELEMENT
Define *NameString
Prototype.l Proto_CertGetNameString(*CertContext.CERT_CONTEXT, dwType.l, dwFlags.l, *pvTypePara, *NameString, cchNameString.l)
Prototype Proto_CertFreeCertificateChain(*ChainContext.CERT_CHAIN_CONTEXT)
Global CertGetNameString.Proto_CertGetNameString
Global CertFreeCertificateChain.Proto_CertFreeCertificateChain
If OpenLibrary(0, "crypt32.dll")
CertGetNameString = GetFunction(0, "CertGetNameStringW")
CertFreeCertificateChain = GetFunction(0, "CertFreeCertificateChain")
Else
End
EndIf
hInet = InternetOpen_("", 0, #Null, #Null, 0)
If hInet
hConnect = InternetConnect_(hInet, "ipinfo.io", #INTERNET_DEFAULT_HTTPS_PORT, #Null, #Null, #INTERNET_SERVICE_HTTP, 0, @dwContext)
If hConnect
hRequest = HttpOpenRequest_(hConnect, "GET", "/8.8.8.8/org", #Null, #Null, #Null, #INTERNET_FLAG_SECURE, @dwContext)
If hRequest
If HttpSendRequest_(hRequest, #Null, 0, #Null, 0)
cbCertSize = SizeOf(CERT_CHAIN_CONTEXT)
If InternetQueryOption_(hRequest, #INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT , @*CertCtx, @cbCertSize)
*ChainContext = *CertCtx
Debug "The size of the chain context is " + Str(*ChainContext\cbSize)
Debug Str(*ChainContext\cChain) + " simple chains found."
Debug ""
Debug "Status For the chain(s):"
Debug ""
For i = 0 To *ChainContext\cChain - 1
Debug "Chain " + Str(i + 1)
Debug ""
*simpleCertificateChainWithinContext = PeekL(*ChainContext\rgpChain + i * 4)
Debug "ChainElements: " + Str(*simpleCertificateChainWithinContext\cElement)
; For each certificate chain in this context...
For simpleCertChainIndex = 0 To *simpleCertificateChainWithinContext\cElement - 1
Debug ""
Debug "ChainElement " + Str(simpleCertChainIndex + 1)
; get the CertContext from the Array
*SimpleChain = PeekL(*simpleCertificateChainWithinContext\rgpElement + simpleCertChainIndex * 4)
*CertContext = *SimpleChain\CertContext
;-------------------------------------------------------------------
; Find And print the name of the subject of the certificate
; just retrieved.
*NameString = AllocateMemory(128)
If *NameString
If CertGetNameString(*CertContext, #CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, #Null, *NameString, 128)
Debug "Certificate for " + PeekS(*NameString) + " has been retrieved"
Else
Debug "CertGetName failed."
EndIf
FreeMemory(*NameString)
EndIf
; Get the issuer now...
*NameString = AllocateMemory(128)
If *NameString
If CertGetNameString(*CertContext, #CERT_NAME_SIMPLE_DISPLAY_TYPE, #CERT_NAME_ISSUER_FLAG, #Null, *NameString, 128)
Debug "Certificate issuer is " + PeekS(*NameString)
Else
Debug "CertGetName failed."
EndIf
FreeMemory(*NameString)
EndIf
Next simpleCertChainIndex
Next i
CertFreeCertificateChain(*CertCtx)
Else
Debug "InternetQueryOption Error: " + Str(GetLastError_())
EndIf
Else
Debug "HTTPSendRequest Error: " + Str(GetLastError_())
EndIf
Else
Debug "HttpOpenRequest Error: " + Str(GetLastError_())
EndIf
Else
Debug "InternetConnect Error: " + Str(GetLastError_())
EndIf
Else
Debug "InternetOpen Error: " + Str(GetLastError_())
EndIf
No, that's definately Rashadfirace wrote:You are the KING of WINAPI.
Infratec kindly provided a 64-bit solution here:tatanas wrote:Sorry to dig up this topic but I'm stucked with a certificate problem with httprequest(). (viewtopic.php?f=13&t=74640)
I would like to download the certificate of a switch. I found your code infratec but as you said, it needs some adjustments to work with 64bits PB and I don't know what variable or Peek I should modify.
Could you tell me what I should change ?
Thanks.