views:

1035

answers:

1

Does anyone know how I could go about finding out when a certificate for user is set to expire? I know I can get pull all of the certificates for a given user by usin the following code:

Set objUserTemplate = _
    GetObject("LDAP://cn=userTemplate,OU=Management,dc=NA,dc=fabrikam,dc=com")
arrUserCertificates = objUserTemplate.GetEx("userCertificate")

But then how do I go about polling the expiration date for a given certificate? I did see this java code here: http://forums.novell.com/novell-developer-forums/dev-ldap/364977-q-retrieving-users-public-key-over-ldap.html,

X509Certificate cert = ( X509Certificate )it.next();
java.util.Date expires = cert.getNotAfter();
GregorianCalendar calNow = new GregorianCalendar();
GregorianCalendar calExp = new GregorianCalendar();
calExp.setTime( expires );
//issuerDN = cert.getIssuerDN().getName();
int daysTilExp = com.willeke.utility.DateUtils.daysPast( calExp );
long diffDays = com.willeke.utility.DateUtils.diffDayPeriods( calNow,
calExp );
if( diffDays <= 0 )
{
String mex = " Will expire in: " + diffDays + " days!";

but I'm not sure if I can use the getNotAfter method within VB, or how I would go about doing it. Does anyone have any ideas? If at all possible I would like help in doing this query in VBScript/VB.Net/VBA, etc.

I did find this VBScript code here which seems to be doing what I am trying to accomplish, but is seems pretty complex, where as the java code seemed much simpler. Is there an easier way to do this query in some flavor of VB?

From the cruto site:

On Error Resume Next

Const E_ADS_PROPERTY_NOT_FOUND  = &h8000500D
Const ForWriting = 2
Const WshRunning = 0

Set objUser = GetObject _
    ("GC://cn=MyerKen,ou=Management,dc=NA,dc=fabrikam,dc=com")
objUser.GetInfoEx Array("userCertificate"), 0
arrUserCertificates = objUser.GetEx("userCertificate")

If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then
    WScript.Echo "No assigned certificates"
    WScript.Quit
Else
    Set objShell = CreateObject("WScript.Shell")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    strPath = "." 
    intFileCounter = 0

    For Each arrUserCertificate in arrUserCertificates
        strFileName = "file" & intFileCounter
        strFullName = objFSO.BuildPath(strPath, strFileName)
        Set objFile = objFSO.OpenTextFile(strFullName, ForWriting, True)

        For i = 1 To LenB(arrUserCertificate)
            ReDim Preserve arrUserCertificatesChar(i - 1)
            arrUserCertificatesChar(i-1) = _
                Hex(AscB(MidB(arrUserCertificate, i, 3)))
        Next

        intCounter=0
        For Each HexVal in arrUserCertificatesChar
            intCounter=intCounter + 1
            If Len(HexVal) = 1 Then 
                objFile.Write(0 & HexVal & " ")
            Else
                objFile.Write(HexVal & " ")
            End If
        Next
        objFile.Close
        Set objFile = Nothing

        Set objExecCmd1 = objShell.Exec _
            ("certutil -decodeHex " & strFileName & " " & strFileName & ".cer")
        Do While objExecCmd1.Status = WshRunning
            WScript.Sleep 100
        Loop
        Set objExecCmd1 = Nothing

        Set objExecCmd2 = objShell.Exec("certutil " & strFileName & ".cer")
        Set objStdOut = objExecCmd2.StdOut
        Set objExecCmd2 = Nothing

        WScript.Echo VbCrLf & "Certificate " & intFileCounter + 1
        While Not objStdOut.AtEndOfStream
            strLine = objStdOut.ReadLine
            If InStr(strLine, "Issuer:") Then
                WScript.Echo Trim(strLine)
                WScript.Echo vbTab & Trim(objStdOut.ReadLine)
            End If
            If InStr(strLine, "Subject:") Then
                Wscript.Echo Trim(strLine)
                WScript.Echo vbTab & Trim(objStdOut.ReadLine)
            End If
            If InStr(strLine, "NotAfter:") Then
                strLine = Trim(strLine)
                WScript.Echo "Expires:"
                Wscript.Echo vbTab & Mid(strLine, 11)
            End If
        Wend

        objFSO.DeleteFile(strFullName)
        objFSO.DeleteFile(strPath & "\" & strFileName & ".cer") 

        intFileCounter = intFileCounter + 1
    Next
End If

Update I did see that I could import the certificate into the CAPICOM object to return back the ValidToDate Property, but apparently the format inwhich it is stored in AD is of the wrong format according to this posting here: http://www.powershellcommunity.org/Forums/tabid/54/aff/4/aft/1639/afv/topic/Default.aspx

Does anyone know what format is expected from the CAPICOM import function?

+1  A: 

Microsoft has an ActiveX control called CAPICOM which allows you to programmatically access various properties of the certificate. The MSDN CAPICOM article details these functions. The Platform SDK (linked from the Where to get it link) includes samples, documentation and the redistributable control. The samples include VBScript examples. I found the download for the Platform SDK here.

In short, once you've retrieved the certificate, you're looking for the ValidFromDate and ValidToDate properties.

Matt Newby
I did see this powershell code (http://bit.ly/9IdB8) where he showed how I could possibly do it using Capicom, but again the code didn't work for him as it returned the cert in a format which Capicom could not recognize: $pfad="LDAP://server/cn=" + $tnummer + ",ou=operationalaccounts,ou=useraccounts,dc=domain,dc=net"$user=New-Object DirectoryServices.DirectoryEntry($pfad)$userCerts=$user.GetEX("userCertificate") !!!may in this line I get the wrong format$oCert= New-Object -com "CAPICOM.Certificate"foreach ($Certificate in $userCerts){$oCert.import($Certificate)$oCert.ValidToDate}
mrTomahawk