Home | History | Annotate | Download | only in lib
      1 '***************************************************************************
      2 '*                                  _   _ ____  _
      3 '*  Project                     ___| | | |  _ \| |
      4 '*                             / __| | | | |_) | |
      5 '*                            | (__| |_| |  _ <| |___
      6 '*                             \___|\___/|_| \_\_____|
      7 '*
      8 '* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel (a] haxx.se>, et al.
      9 '*
     10 '* This software is licensed as described in the file COPYING, which
     11 '* you should have received as part of this distribution. The terms
     12 '* are also available at http://curl.haxx.se/docs/copyright.html.
     13 '*
     14 '* You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15 '* copies of the Software, and permit persons to whom the Software is
     16 '* furnished to do so, under the terms of the COPYING file.
     17 '*
     18 '* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19 '* KIND, either express or implied.
     20 '*
     21 '***************************************************************************
     22 '* Script to fetch certdata.txt from Mozilla.org site and create a
     23 '* ca-bundle.crt for use with OpenSSL / libcurl / libcurl bindings
     24 '* Requires WinHttp.WinHttpRequest.5.1 and ADODB.Stream which are part of
     25 '* W2000 SP3 or later, WXP SP1 or later, W2003 Server SP1 or later.
     26 '* Hacked by Guenter Knauf
     27 '***************************************************************************
     28 Option Explicit
     29 Const myVersion = "0.3.9"
     30 
     31 Const myUrl = "http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt"
     32 Const myOpenssl = "openssl.exe"
     33 
     34 Const myCdSavF = FALSE       ' Flag: save downloaded data to file certdata.txt
     35 Const myCaBakF = TRUE        ' Flag: backup existing ca-bundle certificate
     36 Const myAskLiF = TRUE        ' Flag: display certdata.txt license agreement
     37 Const myAskTiF = TRUE        ' Flag: ask to include certificate text info
     38 Const myWrapLe = 76          ' Default length of base64 output lines
     39 
     40 '******************* Nothing to configure below! *******************
     41 Dim objShell, objNetwork, objFSO, objHttp
     42 Dim myBase, mySelf, myFh, myTmpFh, myCdData, myCdFile, myCaFile, myTmpName, myBakNum, myOptTxt, i
     43 Set objNetwork = WScript.CreateObject("WScript.Network")
     44 Set objShell = WScript.CreateObject("WScript.Shell")
     45 Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
     46 Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest.5.1")
     47 If objHttp Is Nothing Then Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest")
     48 myBase = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\"))
     49 mySelf = Left(WScript.ScriptName, InstrRev(WScript.ScriptName, ".") - 1) & " " & myVersion
     50 myCdFile = Mid(myUrl, InstrRev(myUrl, "/") + 1)
     51 myCaFile = "ca-bundle.crt"
     52 myTmpName = InputBox("Enter output filename:", mySelf, myCaFile)
     53 If Not (myTmpName = "") Then
     54   myCaFile = myTmpName
     55 End If
     56 ' Lets ignore SSL invalid cert errors
     57 objHttp.Option(4) = 256 + 512 + 4096 + 8192
     58 objHttp.SetTimeouts 0, 5000, 10000, 10000
     59 objHttp.Open "GET", myUrl, FALSE
     60 objHttp.setRequestHeader "User-Agent", WScript.ScriptName & "/" & myVersion
     61 objHttp.Send ""
     62 If Not (objHttp.Status = 200) Then
     63   MsgBox("Failed to download '" & myCdFile & "': " & objHttp.Status & " - " & objHttp.StatusText), vbCritical, mySelf
     64   WScript.Quit 1
     65 End If
     66 ' Convert data from ResponseBody instead of using ResponseText because of UTF-8
     67 myCdData = ConvertBinaryData(objHttp.ResponseBody)
     68 Set objHttp = Nothing
     69 ' Write received data to file if enabled
     70 If (myCdSavF = TRUE) Then
     71   Set myFh = objFSO.OpenTextFile(myCdFile, 2, TRUE)
     72   myFh.Write myCdData
     73   myFh.Close
     74 End If
     75 ' Backup exitsing ca-bundle certificate file
     76 If (myCaBakF = TRUE) Then
     77   If objFSO.FileExists(myCaFile) Then
     78     Dim myBakFile, b
     79     b = 1
     80     myBakFile = myCaFile & ".~" & b & "~"
     81     While objFSO.FileExists(myBakFile)
     82       b = b + 1
     83       myBakFile = myCaFile & ".~" & b & "~"
     84     Wend
     85     Set myTmpFh = objFSO.GetFile(myCaFile)
     86     myTmpFh.Move myBakFile
     87   End If
     88 End If
     89 If (myAskTiF = TRUE) Then
     90   If (6 = objShell.PopUp("Do you want to include text information about each certificate?" & vbLf & _
     91           "(requires OpenSSL commandline in current directory or in search path)",, _
     92           mySelf, vbQuestion + vbYesNo + vbDefaultButton2)) Then
     93     myOptTxt = TRUE
     94   Else
     95     myOptTxt = FALSE
     96   End If
     97 End If
     98 ' Process the received data
     99 Dim myLines, myPattern, myInsideCert, myInsideLicense, myLicenseText, myNumCerts, myNumSkipped
    100 Dim myLabel, myOctets, myData, myPem, myRev, myUntrusted, j
    101 myNumSkipped = 0
    102 myNumCerts = 0
    103 myData = ""
    104 myLines = Split(myCdData, vbLf, -1)
    105 Set myFh = objFSO.OpenTextFile(myCaFile, 2, TRUE)
    106 myFh.Write "##" & vbLf
    107 myFh.Write "## " & myCaFile & " -- Bundle of CA Root Certificates" & vbLf
    108 myFh.Write "##" & vbLf
    109 myFh.Write "## Converted at: " & Now & vbLf
    110 myFh.Write "##" & vbLf
    111 myFh.Write "## This is a bundle of X.509 certificates of public Certificate Authorities" & vbLf
    112 myFh.Write "## (CA). These were automatically extracted from Mozilla's root certificates" & vbLf
    113 myFh.Write "## file (certdata.txt).  This file can be found in the mozilla source tree:" & vbLf
    114 myFh.Write "## '/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt'" & vbLf
    115 myFh.Write "##" & vbLf
    116 myFh.Write "## It contains the certificates in PEM format and therefore" & vbLf
    117 myFh.Write "## can be directly used with curl / libcurl / php_curl, or with" & vbLf
    118 myFh.Write "## an Apache+mod_ssl webserver for SSL client authentication." & vbLf
    119 myFh.Write "## Just configure this file as the SSLCACertificateFile." & vbLf
    120 myFh.Write "##" & vbLf
    121 myFh.Write vbLf
    122 For i = 0 To UBound(myLines)
    123   If InstrRev(myLines(i), "CKA_LABEL ") Then
    124     myPattern = "^CKA_LABEL\s+[A-Z0-9]+\s+""(.+?)"""
    125     myLabel = RegExprFirst(myPattern, myLines(i))
    126   End If
    127   If (myInsideCert = TRUE) Then
    128     If InstrRev(myLines(i), "END") Then
    129       myInsideCert = FALSE
    130       While (i < UBound(myLines)) And Not (myLines(i) = "#")
    131         i = i + 1
    132         If InstrRev(myLines(i), "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR") Then
    133           myUntrusted = FALSE
    134         End If
    135       Wend
    136       If (myUntrusted = TRUE) Then
    137         myNumSkipped = myNumSkipped + 1
    138       Else
    139         myFh.Write myLabel & vbLf
    140         myFh.Write String(Len(myLabel), "=") & vbLf
    141         myPem = "-----BEGIN CERTIFICATE-----" & vbLf & _
    142                 Base64Encode(myData) & vbLf & _
    143                 "-----END CERTIFICATE-----" & vbLf
    144         If (myOptTxt = FALSE) Then
    145           myFh.Write myPem & vbLf
    146         Else
    147           Dim myCmd, myRval, myTmpIn, myTmpOut
    148           myTmpIn = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
    149           myTmpOut = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
    150           Set myTmpFh = objFSO.OpenTextFile(myTmpIn, 2, TRUE)
    151           myTmpFh.Write myPem
    152           myTmpFh.Close
    153           myCmd = myOpenssl & " x509 -md5 -fingerprint -text -inform PEM" & _
    154                   " -in " & myTmpIn & " -out " & myTmpOut
    155           myRval = objShell.Run (myCmd, 0, TRUE)
    156           objFSO.DeleteFile myTmpIn, TRUE
    157           If Not (myRval = 0) Then
    158             MsgBox("Failed to process PEM cert with OpenSSL commandline!"), vbCritical, mySelf
    159             objFSO.DeleteFile myTmpOut, TRUE
    160             WScript.Quit 3
    161           End If
    162           Set myTmpFh = objFSO.OpenTextFile(myTmpOut, 1)
    163           myFh.Write myTmpFh.ReadAll & vbLf
    164           myTmpFh.Close
    165           objFSO.DeleteFile myTmpOut, TRUE
    166         End If
    167         myNumCerts = myNumCerts + 1
    168       End If
    169     Else
    170       myOctets = Split(myLines(i), "\")
    171       For j = 1 To UBound(myOctets)
    172         myData = myData & Chr(CByte("&o" & myOctets(j)))
    173       Next
    174     End If
    175   End If
    176   If InstrRev(myLines(i), "CVS_ID ") Then
    177     myPattern = "^CVS_ID\s+""(.+?)"""
    178     myRev = RegExprFirst(myPattern, myLines(i))
    179     myFh.Write "# " & myRev & vbLf & vbLf
    180   End If
    181   If InstrRev(myLines(i), "CKA_VALUE MULTILINE_OCTAL") Then
    182     myInsideCert = TRUE
    183     myUntrusted = TRUE
    184     myData = ""
    185   End If
    186   If InstrRev(myLines(i), "***** BEGIN LICENSE BLOCK *****") Then
    187     myInsideLicense = TRUE
    188   End If
    189   If (myInsideLicense = TRUE) Then
    190     myFh.Write myLines(i) & vbLf
    191     myLicenseText = myLicenseText & Mid(myLines(i), 2) & vbLf
    192   End If
    193   If InstrRev(myLines(i), "***** END LICENSE BLOCK *****") Then
    194     myInsideLicense = FALSE
    195     If (myAskLiF = TRUE) Then
    196       If Not (6 = objShell.PopUp(myLicenseText & vbLf & _
    197               "Do you agree to the license shown above (required to proceed) ?",, _
    198               mySelf, vbQuestion + vbYesNo + vbDefaultButton1)) Then
    199         myFh.Close
    200         objFSO.DeleteFile myCaFile, TRUE
    201         WScript.Quit 2
    202       End If
    203     End If
    204   End If
    205 Next
    206 myFh.Close
    207 objShell.PopUp "Done (" & myNumCerts & " CA certs processed, " & myNumSkipped & _
    208                " untrusted skipped).", 20, mySelf, vbInformation
    209 WScript.Quit 0
    210 
    211 Function ConvertBinaryData(arrBytes)
    212   Dim objStream
    213   Set objStream = CreateObject("ADODB.Stream")
    214   objStream.Open
    215   objStream.Type = 1
    216   objStream.Write arrBytes
    217   objStream.Position = 0
    218   objStream.Type = 2
    219   objStream.Charset = "ascii"
    220   ConvertBinaryData = objStream.ReadText
    221   Set objStream = Nothing
    222 End Function
    223 
    224 Function RegExprFirst(SearchPattern, TheString)
    225   Dim objRegExp, Matches                        ' create variables.
    226   Set objRegExp = New RegExp                    ' create a regular expression.
    227   objRegExp.Pattern = SearchPattern             ' sets the search pattern.
    228   objRegExp.IgnoreCase = TRUE                   ' set to ignores case.
    229   objRegExp.Global = TRUE                       ' set to gloabal search.
    230   Set Matches = objRegExp.Execute(TheString)    ' do the search.
    231   If (Matches.Count) Then
    232     RegExprFirst = Matches(0).SubMatches(0)     ' return first match.
    233   Else
    234     RegExprFirst = ""
    235   End If
    236   Set objRegExp = Nothing
    237 End Function
    238 
    239 Function Base64Encode(inData)
    240   Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    241   Dim cOut, sOut, lWrap, I
    242   lWrap = Int(myWrapLe * 3 / 4)
    243 
    244   'For each group of 3 bytes
    245   For I = 1 To Len(inData) Step 3
    246     Dim nGroup, pOut, sGroup
    247 
    248     'Create one long from this 3 bytes.
    249     nGroup = &H10000 * Asc(Mid(inData, I, 1)) + _
    250              &H100 * MyASC(Mid(inData, I + 1, 1)) + _
    251              MyASC(Mid(inData, I + 2, 1))
    252 
    253     'Oct splits the long To 8 groups with 3 bits
    254     nGroup = Oct(nGroup)
    255 
    256     'Add leading zeros
    257     nGroup = String(8 - Len(nGroup), "0") & nGroup
    258 
    259     'Convert To base64
    260     pOut = Mid(Base64, CLng("&o" & Mid(nGroup, 1, 2)) + 1, 1) & _
    261            Mid(Base64, CLng("&o" & Mid(nGroup, 3, 2)) + 1, 1) & _
    262            Mid(Base64, CLng("&o" & Mid(nGroup, 5, 2)) + 1, 1) & _
    263            Mid(Base64, CLng("&o" & Mid(nGroup, 7, 2)) + 1, 1)
    264 
    265     'Add the part To OutPut string
    266     sOut = sOut + pOut
    267 
    268     'Add a new line For Each myWrapLe chars In dest
    269     If (I < Len(inData) - 2) Then
    270       If (I + 2) Mod lWrap = 0 Then sOut = sOut & vbLf
    271     End If
    272   Next
    273   Select Case Len(inData) Mod 3
    274     Case 1: '8 bit final
    275       sOut = Left(sOut, Len(sOut) - 2) & "=="
    276     Case 2: '16 bit final
    277       sOut = Left(sOut, Len(sOut) - 1) & "="
    278   End Select
    279   Base64Encode = sOut
    280 End Function
    281 
    282 Function MyASC(OneChar)
    283   If OneChar = "" Then MyASC = 0 Else MyASC = Asc(OneChar)
    284 End Function
    285 
    286 
    287