It is currently Sun Dec 16, 2018 6:52 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: How to download SSL certificate from a server
PostPosted: Sun Nov 04, 2018 10:33 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Nov 09, 2011 8:58 am
Posts: 367
I'm not sure how to download (to file or memory) the SSL certificate from an HTTPS server in PB.
Any ideas?

In Python for instance, that's very simple:

Code:
import ssl
ssl.get_server_certificate(('server.test.com', 443))

_________________
I'm the eternal noob.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Sun Nov 04, 2018 11:09 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Nov 09, 2011 8:58 am
Posts: 367
Apparently this could be a way for Windows: https://blogs.msdn.microsoft.com/jpsand ... in_context

But it looks complicated - to me, at least.

_________________
I'm the eternal noob.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Sun Nov 04, 2018 11:23 am 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4051
Location: Germany
In PB it's nearly the same ...

You have to write a wrapper for OpenSSL, then you can use the same function :wink:

Or you can use libcurl, but I don't know if you can get all informations:

https://curl.haxx.se/libcurl/c/CURLINFO_CERTINFO.html

You can nearly direct convert this example to PB with our libcurl.pbi


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Sun Nov 04, 2018 12:22 pm 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4051
Location: Germany
Ups..

I had to add some sructures and definitions to libcurl.pbi
But on windows it results in 0 certs maybe that openssl is not used by the PB libcurl.
I have to check the code on linux.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Thu Nov 08, 2018 7:56 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Nov 09, 2011 8:58 am
Posts: 367
Yes it does seem that the embedded PB libcurl does not support that feature, unfortunately.

So if someone knows how to translate the following MSDN snippet to PB, it would be really great:

Code:
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"));
}

_________________
I'm the eternal noob.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Thu Nov 08, 2018 9:29 pm 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4051
Location: Germany
Hi,

maybe this works a bit (or not)
Code:
#INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105

#CERT_NAME_SIMPLE_DISPLAY_TYPE = 4

#CERT_NAME_ISSUER_FLAG = $00000001

...


removed. See working code below.


Last edited by infratec on Sat Nov 10, 2018 12:28 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Fri Nov 09, 2018 10:48 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Nov 09, 2011 8:58 am
Posts: 367
Thanks infratec! I'm impressed at how fast you could convert it, even if it doesn't work yet.

This is my simplified test code. Not sure where it goes wrong...

Code:
#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)


_________________
I'm the eternal noob.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Fri Nov 09, 2018 6:55 pm 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4051
Location: Germany
One step further:

Code:
EnableExplicit

#INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105

#CERT_NAME_SIMPLE_DISPLAY_TYPE = 4

#CERT_NAME_ISSUER_FLAG = $00000001

...



removed. See working code below.


Last edited by infratec on Sat Nov 10, 2018 12:29 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Sat Nov 10, 2018 11:33 am 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4051
Location: Germany
I did it:

Code:
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


The Problem was: pointer to pointer array
In PB we have to receive the correct entries 'by hand'

When you use 64bit version of PB you have to adjust some things...

Bernd


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Sat Nov 10, 2018 5:09 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Nov 09, 2011 8:58 am
Posts: 367
Wow, that's an amazing job.
You are the KING of WINAPI. :!: :!: :!:
Now I will study the code...

Thanks again!

_________________
I'm the eternal noob.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to download SSL certificate from a server
PostPosted: Sat Nov 10, 2018 5:29 pm 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4051
Location: Germany
firace wrote:
You are the KING of WINAPI. :!: :!: :!:


No, that's definately Rashad :!:


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye