Gertsen

SSL certificate information

20 posts in this topic

I need a script that reads a remote SSL certificate, and gives me access to information about it, like expiration date.

Other info I would like, but can live without is:

  • Issuer
  • Certificate Name (CN)
  • Valid from (date)
  • Expiration (date)
  • Domain (what the certificate is issued for)
  • Other misc info
I tried using winhttp.winhttprequest.5.1 and Msxml2.ServerXMLHTTP.3.0 but they only seem to be able to connect to SSL servers, not accually read the certificate itself?

I can get them to give an error message if the certificate has expired, but by then it is too late :P

The reason I need this, is that it's quite bad when an SSL certificate expires, so I often need to check the expiration date of alot of certificates, and it would take a long time to manually open each site in IE or similar, to lookup the date...

So I want to make a tool that checks the expiration date, and sends me a mail if there is a month or less left before it expires.

I can figure out the rest of the program myself, it's getting the certificate information that is holding me back :(

Share this post


Link to post
Share on other sites



#4 ·  Posted (edited)

I found this script though:

http://weblogs.asp.net/mikedopp/archive/20...tom-script.aspx

Only I can't seem to translate the "For each" loop it uses (I'm new to AutoIt's language)

Also it only seems to be able to see the certificates installed on my local computer, not the remote servers, but I hope I can change that once I get the script working better.

Here is what I have so far, though it dosen't work yet..

#include <INet.au3>

Global Const $CAPICOM_LOCAL_MACHINE_STORE_TEST = 1

Global Const $CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1     
Global Const $CAPICOM_STORE_OPEN_READ_ONLY_TEST = 0

Global Const Enum $CAPICOM_ACTIVE_DIRECTORY_USER_STORE, _
  $CAPICOM_CURRENT_USER_STORE, _
  $CAPICOM_LOCAL_MACHINE_STORE, _
  $CAPICOM_MEMORY_STORE, _
  $CAPICOM_SMART_CARD_USER_STORE

Global Const Enum $CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED, _
  $CAPICOM_STORE_OPEN_READ_ONLY, _
  $CAPICOM_STORE_OPEN_READ_WRITE

$Store = ObjCreate("CAPICOM.Store")
;$Store.Open($CAPICOM_LOCAL_MACHINE_STORE, "CAPICOM_MY_STORE", $CAPICOM_STORE_OPEN_READ_ONLY)
$Store.Open($CAPICOM_LOCAL_MACHINE_STORE_TEST, "My", $CAPICOM_STORE_OPEN_READ_ONLY_TEST)

$Certificates = $Store.Certificates.Find($CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, "mail.google.com", 0)

For Each $Certificate in $Certificates
    ConsoleWrite("-->" & $Certificate.ValidFromDate & @LF)
Next

I get the following error:

>"C:\Programmer\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "U:\Dokumenter\AutoIt\sslcheck\sslcheck2.au3"

U:\Dokumenter\AutoIt\sslcheck\sslcheck2.au3 (24) : ==> "For" statement is badly formatted.:

For Each $Certificate in $Certificates

For ^ ERROR

>Exit code: 1 Time: 0.333

So clearly the For Each dosen't work :-(

Edited by Gertsen

Share this post


Link to post
Share on other sites

I get the following error:

>"C:\Programmer\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "U:\Dokumenter\AutoIt\sslcheck\sslcheck2.au3"

U:\Dokumenter\AutoIt\sslcheck\sslcheck2.au3 (24) : ==> "For" statement is badly formatted.:

For Each $Certificate in $Certificates

For ^ ERROR

>Exit code: 1 Time: 0.333

So clearly the For Each dosen't work :-(

Yep - this way it won't work. Check out this, it at least gives no compile errors (but also no results :P ):

#include <INet.au3>

Global Const $CAPICOM_LOCAL_MACHINE_STORE_TEST = 1
Global Const $CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1        
Global Const $CAPICOM_STORE_OPEN_READ_ONLY_TEST = 0
Global Enum $CAPICOM_ACTIVE_DIRECTORY_USER_STORE, $CAPICOM_CURRENT_USER_STORE, $CAPICOM_LOCAL_MACHINE_STORE, $CAPICOM_MEMORY_STORE, $CAPICOM_SMART_CARD_USER_STORE
Global Enum $CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED, $CAPICOM_STORE_OPEN_READ_ONLY, $CAPICOM_STORE_OPEN_READ_WRITE

$Store = ObjCreate("CAPICOM.Store")
;~ $Store.Open($CAPICOM_LOCAL_MACHINE_STORE, "CAPICOM_MY_STORE", $CAPICOM_STORE_OPEN_READ_ONLY)
$Store.Open($CAPICOM_LOCAL_MACHINE_STORE_TEST, "Other People", $CAPICOM_STORE_OPEN_READ_ONLY_TEST)

$Certificates = $Store.Certificates.Find($CAPICOM_ACTIVE_DIRECTORY_USER_STORE, "www.google.com", 0)

For $Certificate in $Certificates
    ConsoleWrite("-->" & $Certificate.ValidFromDate & @LF)
Next

Share this post


Link to post
Share on other sites

Hmm I got this working, but it will only check my own domain user-account (in this case "mage")...

Any ideas on how to get it to check external servers (though still on this LAN) ?

Global Const $CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1     
Global Const Enum $CAPICOM_ACTIVE_DIRECTORY_USER_STORE, _
  $CAPICOM_CURRENT_USER_STORE, _
  $CAPICOM_LOCAL_MACHINE_STORE, _
  $CAPICOM_MEMORY_STORE, _
  $CAPICOM_SMART_CARD_USER_STORE
Global Const Enum $CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED, _
  $CAPICOM_STORE_OPEN_READ_ONLY, _
  $CAPICOM_STORE_OPEN_READ_WRITE

$Store = ObjCreate("CAPICOM.Store")
$Store.Open($CAPICOM_LOCAL_MACHINE_STORE, "My", $CAPICOM_STORE_OPEN_READ_ONLY)

$Certificates = $Store.Certificates.Find($CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, "mage", 0)

For $Certificate in $Certificates
    ConsoleWrite("Valid From: " & $Certificate.ValidFromDate & @LF)
    ConsoleWrite("Valid To: " & $Certificate.ValidToDate & @LF)
    ConsoleWrite("Subject Name: " & $Certificate.SubjectName & @LF)
    ConsoleWrite("Issued By: " & $Certificate.IssuerName & @LF)
Next

Output:

>"C:\Programmer\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "U:\Dokumenter\AutoIt\sslcheck\sslcheck2.au3"

Valid From: 20081008091309

Valid To: 20091008091309

Subject Name: CN=mage, OU=TestOY, OU=Users, DC=TestDomain, DC=dk

Issued By: CN=Test, DC=TestDomain, DC=dk

>Exit code: 0 Time: 0.223

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Updated to show a nicer date, and calculate how many days remain before expiration.

Now I "just" need it to be able to check certificates on other servers, not just my local pc.

#Include <Date.au3>
Global Const $CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1     
Global Const Enum $CAPICOM_ACTIVE_DIRECTORY_USER_STORE, _
  $CAPICOM_CURRENT_USER_STORE, _
  $CAPICOM_LOCAL_MACHINE_STORE, _
  $CAPICOM_MEMORY_STORE, _
  $CAPICOM_SMART_CARD_USER_STORE
Global Const Enum $CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED, _
  $CAPICOM_STORE_OPEN_READ_ONLY, _
  $CAPICOM_STORE_OPEN_READ_WRITE

$Store = ObjCreate("CAPICOM.Store")
$Store.Open($CAPICOM_LOCAL_MACHINE_STORE, "My", $CAPICOM_STORE_OPEN_READ_ONLY)
$Certificates = $Store.Certificates.Find($CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, "mage", 0)

For $Certificate in $Certificates
    ConsoleWrite("Valid From: " & _FixDate($Certificate.ValidFromDate) & @LF)
    ConsoleWrite("Valid To: " & _FixDate($Certificate.ValidToDate) & @LF)
    ConsoleWrite("Subject Name: " & $Certificate.SubjectName & @LF)
    ConsoleWrite("Issued By: " & $Certificate.IssuerName & @LF)
    $test = _DateDiff("D",_FixDate($Certificate.ValidFromDate),_FixDate($Certificate.ValidToDate))
    ConsoleWrite("Days remaining: " & $test & @LF)
Next

Func _FixDate($inDate)
    Return StringMid($inDate,1,4) & "/" & StringMid($inDate,5,2) & "/" & StringMid($inDate,7,2)
EndFunc ;==>_FixDate
Edited by Gertsen

Share this post


Link to post
Share on other sites

This still fails. Even what you gave us has no reason to work, because your constants are wrong (GLOBAL ENUM, not GLOBAL CONST ENUM). Regardless I found all the constants. I also added some error checking, but I still fails. :P

#Include <Date.au3>
Global $Store, $Certificates, $Certificate

Global $SubjectName = "My"

GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_SHA1_HASH            = 0
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME      = 1
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_ISSUER_NAME        = 2
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_ROOT_NAME            = 3
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_TEMPLATE_NAME        = 4
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_EXTENSION            = 5
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY    = 6
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_APPLICATION_POLICY   = 7
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_CERTIFICATE_POLICY   = 8
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_TIME_VALID          = 9
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_TIME_NOT_YET_VALID   = 10
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_TIME_EXPIRED      = 11
GLOBAL CONST $CAPICOM_CERTIFICATE_FIND_KEY_USAGE            = 12

GLOBAL CONST $CAPICOM_MEMORY_STORE                = 0
GLOBAL CONST $CAPICOM_LOCAL_MACHINE_STORE          = 1
GLOBAL CONST $CAPICOM_CURRENT_USER_STORE            = 2
GLOBAL CONST $CAPICOM_ACTIVE_DIRECTORY_USER_STORE   = 3
GLOBAL CONST $CAPICOM_SMART_CARD_USER_STORE      = 4

GLOBAL CONST $CAPICOM_STORE_OPEN_READ_ONLY        = 0
GLOBAL CONST $CAPICOM_STORE_OPEN_READ_WRITE      = 1
GLOBAL CONST $CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED    = 2
GLOBAL CONST $CAPICOM_STORE_OPEN_EXISTING_ONLY    = 128
GLOBAL CONST $CAPICOM_STORE_OPEN_INCLUDE_ARCHIVED   = 256 

$Store = ObjCreate("CAPICOM.Store")
If @error Then
    Msgbox(0,"Remote ObjCreate Test","Failed to open remote Object. Error code: " & hex(@error,8))
    Exit
EndIf
$Store.Open ($CAPICOM_LOCAL_MACHINE_STORE, "MY" , $CAPICOM_STORE_OPEN_READ_ONLY)
$Certificates = $store.Certificates.Find($CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, $SubjectName, 0)

If $certificates.Count > 0 Then
    For $Certificate In $Certificates
        ConsoleWrite("Valid From: " & _FixDate($Certificate.ValidFromDate) & @LF)
        ConsoleWrite("Valid To: " & _FixDate($Certificate.ValidToDate) & @LF)
        ConsoleWrite("Subject Name: " & $Certificate.SubjectName & @LF)
        ConsoleWrite("Issued By: " & $Certificate.IssuerName & @LF)
        $test = _DateDiff("D", _FixDate($Certificate.ValidFromDate), _FixDate($Certificate.ValidToDate))
        ConsoleWrite("Days remaining: " & $test & @LF)
    Next
Else
    ConsoleWrite("No certificates with SubjectName => '" & $SubjectName & "'")
EndIf

Func _FixDate($inDate)
    Return StringMid($inDate, 1, 4) & "/" & StringMid($inDate, 5, 2) & "/" & StringMid($inDate, 7, 2)
EndFunc  ;==>_FixDate

Share this post


Link to post
Share on other sites

Hmm it seems I found my certificate in the $CAPICOM_CURRENT_USER_STORE store - the certificate for my own domain-user from the domain, that is.

I still can't seem to access certificates on other servers or sites.

Perhaps capicom just isn't the way to go?

Or perhaps something else needs to be done with capicom first, there are alot of terms in capicom I don't understand, like "IOU" and "Chains" and lots more...

Share this post


Link to post
Share on other sites

According to MSDN, WinINet has a struct called INTERNET_CERTIFICATE_INFO, but I have no idea how to use/access it.

Have you tried using WinINet before, perhaps you have some hints?

Share this post


Link to post
Share on other sites

I played around with Ultima's fine functions, and so far I have arrived at the code below.

I can now open a connection to a remote ssl server, but I still have no idea how to access the INTERNET_CERTIFICATE_INFO struct :-(

Any ideas?

#include <WinINet.au3>

; Initialize WinINet
_WinINet_Startup()

; Set variables
Global $sServerName = "mail.google.com"
Global $iServerPort = 443
Global $sUsername = Default
Global $sPassword = Default

; Create handles
ConsoleWrite("Opening Internet connection ..." & @LF)
Global $hInternetOpen = _WinINet_InternetOpen("AutoIt/" & @AutoItVersion)
if @error Then
    ConsoleWrite("Open Internet connection: failed." & @LF)
Else
    ConsoleWrite("Open Internet connection: ok." & @LF)
EndIf

ConsoleWrite("Connecting to " & $sServerName & ":" & $iServerPort & " ..." & @LF)
Global $hInternetConnect = _WinINet_InternetConnect($hInternetOpen, $INTERNET_SERVICE_HTTP, $sServerName, $iServerPort, 0, $sUsername, $sPassword)
if @error Then
    ConsoleWrite("Connect to " & $sServerName & ":" & $iServerPort & ": failed." & @LF)
Else
    ConsoleWrite("Connect to " & $sServerName & ":" & $iServerPort & ": ok." & @LF)
EndIf

; Cleanup
_WinINet_InternetCloseHandle($hInternetConnect)
_WinINet_InternetCloseHandle($hInternetOpen)
_WinINet_Shutdown()

ConsoleWrite("End of program..." & @LF)

Share this post


Link to post
Share on other sites

Hi-

I see that now, but having a look I'm not sure how this should be used with _WinINet_InternetQueryOption, so maybe I would post in the thread asking Ultima.

Good luck,

Brett

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

#include <WinINet.au3>

; Initialize WinINet
_WinINet_Startup()

; Set variables
Global $sURIScheme = "https"
Global $sServerName = "mail.google.com"
Global $iServerPort = 443

; Create handles
ConsoleWrite("Opening Internet connection ..." & @LF)
Global $hInternetOpen = _WinINet_InternetOpen("AutoIt/" & @AutoItVersion)
if @error Then
    ConsoleWrite("Open Internet connection: failed." & @LF)
Else
    ConsoleWrite("Open Internet connection: ok." & @LF)
EndIf

Global $hInternetOpenUrl = _WinINet_InternetOpenUrl($hInternetOpen, $sURIScheme & "://" & $sServerName, Default, $INTERNET_FLAG_SECURE)
if @error Then
    ConsoleWrite("Open Internet URL: failed." & @LF)
Else
    ConsoleWrite("Open Internet URL: ok." & @LF)
EndIf

; Query certificate info...
Global $tBuffer = _WinINet_InternetQueryOption($hInternetOpenUrl, $INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT)
Local $tINTERNET_CERTIFICATE_INFO = DllStructCreate($tagINTERNET_CERTIFICATE_INFO, DllStructGetPtr($tBuffer))

Local $tExpiryTime = DllStructCreate("int64", DllStructGetPtr($tINTERNET_CERTIFICATE_INFO, "ExpiryTime"))
ConsoleWrite("Expiry Time (100-nanoseconds): " & DllStructGetData($tExpiryTime, 1) & @LF)

; Cleanup
_WinINet_InternetCloseHandle($hInternetOpenUrl)
_WinINet_InternetCloseHandle($hInternetOpen)
_WinINet_Shutdown()

ConsoleWrite("End of program..." & @LF)

I'm not sure if the structure contains all of the info you need. Reading it might be a pain too, since we need to know the size of the strings, but we can't know without manually scanning for a null character (annoyance and probably a performance killer).

Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

Hello,

Please excuse the automatic translation, my English is bad. :D

I'm looking, too, to use the certificates and the code "-Ultima-" can perfectly used.

But I would like to exploit more information on the certificate, as the name of the issuer, etc..

On the Microsoft site I see that this information can be read into a buffer using a pointer, but I do not know how to do this in Autoit.

http://msdn.microsoft.com/en-us/library/aa385140(VS.85).aspx

Could you help me?

Thank you.

Edited by Whaouu

Share this post


Link to post
Share on other sites

Nobody can help me ?

Share this post


Link to post
Share on other sites

#19 ·  Posted

Nobody can help me ?

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

Hello,

Please excuse the automatic translation, my English is bad. :D

I'm looking, too, to use the certificates and the code "-Ultima-" can perfectly used.

But I would like to exploit more information on the certificate, as the name of the issuer, etc..

On the Microsoft site I see that this information can be read into a buffer using a pointer, but I do not know how to do this in Autoit.

http://msdn.microsoft.com/en-us/library/aa385140(VS.85).aspx

Could you help me?

Thank you.

This script gets the ExpiryTime and issuerinfo,etc..

But how to get the extension info of the certificate as subjectAltName like "DNS Name=www.google.com" ?

#include <WinINet.au3>

; Initialize WinINet
_WinINet_Startup()

; Set variables
Global $sURIScheme = "https"
Global $sServerName = "www.autoitscript.com"
Global $iServerPort = 443

; Create handles
ConsoleWrite("Opening Internet connection ..." & @LF)
Global $hInternetOpen = _WinINet_InternetOpen("AutoIt/" & @AutoItVersion)
if @error Then
    ConsoleWrite("Open Internet connection: failed." & @LF)
Else
    ConsoleWrite("Open Internet connection: ok." & @LF)
EndIf

Global $hInternetOpenUrl = _WinINet_InternetOpenUrl($hInternetOpen, $sURIScheme & "://" & $sServerName, Default, $INTERNET_FLAG_SECURE)
if @error Then
    ConsoleWrite("Open Internet URL: failed." & @LF)
Else
    ConsoleWrite("Open Internet URL: ok." & @LF)
EndIf

; Query certificate info...
Global $tBuffer = _WinINet_InternetQueryOption($hInternetOpenUrl, $INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT)
Local $tINTERNET_CERTIFICATE_INFO = DllStructCreate($tagINTERNET_CERTIFICATE_INFO, DllStructGetPtr($tBuffer))

Local $tExpiryTime = DllStructCreate("int64", DllStructGetPtr($tINTERNET_CERTIFICATE_INFO, "ExpiryTime"))
ConsoleWrite("Expiry Time (100-nanoseconds): " & DllStructGetData($tExpiryTime, 1) & @LF)


Local $tInfo = DllStructCreate("char [256]", DllStructGetData($tINTERNET_CERTIFICATE_INFO, "IssuerInfo"))
ConsoleWrite("IssuerInfo: " & DllStructGetData($tInfo, 1) & @LF)

; Cleanup
_WinINet_InternetCloseHandle($hInternetOpenUrl)
_WinINet_InternetCloseHandle($hInternetOpen)
_WinINet_Shutdown()

ConsoleWrite("End of program..." & @LF)
Edited by jackchen

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now