File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / mk-ca-bundle.vbs
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: '***************************************************************************
    2: '*                                  _   _ ____  _
    3: '*  Project                     ___| | | |  _ \| |
    4: '*                             / __| | | | |_) | |
    5: '*                            | (__| |_| |  _ <| |___
    6: '*                             \___|\___/|_| \_\_____|
    7: '*
    8: '* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@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 https://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.4.0"
   30: 
   31: Const myUrl = "https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt"
   32: 
   33: Const myOpenSSL = "openssl.exe"
   34: Dim myUseOpenSSL
   35: myUseOpenSSL = TRUE          ' Flag: TRUE to use OpenSSL. If TRUE and is not
   36:                              ' found then a warning is shown before continuing.
   37: 
   38: Const myCdSavF = TRUE        ' Flag: save downloaded data to file certdata.txt
   39: Const myCaBakF = TRUE        ' Flag: backup existing ca-bundle certificate
   40: Const myAskLiF = TRUE        ' Flag: display certdata.txt license agreement
   41: Const myWrapLe = 76          ' Default length of base64 output lines
   42: 
   43: ' cert info code doesn't work properly with any recent openssl, leave disabled.
   44: ' Also: we want our certificate output by default to be as similar as possible
   45: ' to mk-ca-bundle.pl and setting this TRUE changes the base64 width to
   46: ' OpenSSL's built-in default width, which is not the same as mk-ca-bundle.pl.
   47: Const myAskTiF = FALSE       ' Flag: ask to include certificate text info
   48: 
   49: '
   50: '******************* Nothing to configure below! *******************
   51: '
   52: Const adTypeBinary = 1
   53: Const adTypeText = 2
   54: Const adSaveCreateNotExist = 1
   55: Const adSaveCreateOverWrite = 2
   56: Dim objShell, objNetwork, objFSO, objHttp
   57: Dim myBase, mySelf, myStream, myTmpFh, myCdData, myCdFile
   58: Dim myCaFile, myTmpName, myBakNum, myOptTxt, i
   59: Set objNetwork = WScript.CreateObject("WScript.Network")
   60: Set objShell = WScript.CreateObject("WScript.Shell")
   61: Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
   62: Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest.5.1")
   63: If objHttp Is Nothing Then Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest")
   64: myBase = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\"))
   65: mySelf = Left(WScript.ScriptName, InstrRev(WScript.ScriptName, ".") - 1) & " " & myVersion
   66: 
   67: myCdFile = Mid(myUrl, InstrRev(myUrl, "/") + 1)
   68: myCaFile = "ca-bundle.crt"
   69: myTmpName = InputBox("It will take a minute to download and parse the " & _
   70:                      "certificate data." & _
   71:                      vbLf & vbLf & _
   72:                      "Please enter the output filename:", mySelf, myCaFile)
   73: If (myTmpName = "") Then
   74:   WScript.Quit 1
   75: End If
   76: myCaFile = myTmpName
   77: If (myCdFile = "") Then
   78:   MsgBox("URL does not contain filename!"), vbCritical, mySelf
   79:   WScript.Quit 1
   80: End If
   81: 
   82: ' Don't use OpenSSL if it's not present.
   83: If (myUseOpenSSL = TRUE) Then
   84:   Dim errnum
   85: 
   86:   On Error Resume Next
   87:   Call objShell.Run("""" & myOpenSSL & """ version", 0, TRUE)
   88:   errnum = Err.Number
   89:   On Error GoTo 0
   90: 
   91:   If Not (errnum = 0) Then
   92:     myUseOpenSSL = FALSE
   93:     MsgBox("OpenSSL was not found so the certificate bundle will not " & _
   94:            "include the SHA256 hash of the raw certificate data file " & _
   95:            "that was used to generate the certificates in the bundle. " & _
   96:            vbLf & vbLf & _
   97:            "This does not have any effect on the certificate output, " & _
   98:            "so this script will continue." & _
   99:            vbLf & vbLf & _
  100:            "If you want to set a custom location for OpenSSL or disable " & _
  101:            "this message then edit the variables at the start of the " & _
  102:            "script."), vbInformation, mySelf
  103:   End If
  104: End If
  105: 
  106: If (myAskTiF = TRUE) And (myUseOpenSSL = TRUE) Then
  107:   If (6 = objShell.PopUp("Do you want to include text information about " & _
  108:                          "each certificate?" & vbLf & _
  109:                          "(Requires OpenSSL.exe in the current directory " & _
  110:                          "or search path)",, _
  111:           mySelf, vbQuestion + vbYesNo + vbDefaultButton2)) Then
  112:     myOptTxt = TRUE
  113:   Else
  114:     myOptTxt = FALSE
  115:   End If
  116: End If
  117: 
  118: ' Uncomment the line below to ignore SSL invalid cert errors
  119: ' objHttp.Option(4) = 256 + 512 + 4096 + 8192
  120: objHttp.SetTimeouts 0, 5000, 10000, 10000
  121: objHttp.Open "GET", myUrl, FALSE
  122: objHttp.setRequestHeader "User-Agent", WScript.ScriptName & "/" & myVersion
  123: objHttp.Send ""
  124: If Not (objHttp.Status = 200) Then
  125:   MsgBox("Failed to download '" & myCdFile & "': " & objHttp.Status & " - " & objHttp.StatusText), vbCritical, mySelf
  126:   WScript.Quit 1
  127: End If
  128: ' Write received data to file if enabled
  129: If (myCdSavF = TRUE) Then
  130:   Call SaveBinaryData(myCdFile, objHttp.ResponseBody)
  131: End If
  132: ' Convert data from ResponseBody instead of using ResponseText because of UTF-8
  133: myCdData = ConvertBinaryToUTF8(objHttp.ResponseBody)
  134: Set objHttp = Nothing
  135: ' Backup exitsing ca-bundle certificate file
  136: If (myCaBakF = TRUE) Then
  137:   If objFSO.FileExists(myCaFile) Then
  138:     Dim myBakFile, b
  139:     b = 1
  140:     myBakFile = myCaFile & ".~" & b & "~"
  141:     While objFSO.FileExists(myBakFile)
  142:       b = b + 1
  143:       myBakFile = myCaFile & ".~" & b & "~"
  144:     Wend
  145:     Set myTmpFh = objFSO.GetFile(myCaFile)
  146:     myTmpFh.Move myBakFile
  147:   End If
  148: End If
  149: 
  150: ' Process the received data
  151: Dim myLines, myPattern, myInsideCert, myInsideLicense, myLicenseText, myNumCerts, myNumSkipped
  152: Dim myLabel, myOctets, myData, myPem, myRev, myUntrusted, j
  153: myNumSkipped = 0
  154: myNumCerts = 0
  155: myData = ""
  156: myLines = Split(myCdData, vbLf, -1)
  157: Set myStream = CreateObject("ADODB.Stream")
  158: myStream.Open
  159: myStream.Type = adTypeText
  160: myStream.Charset = "utf-8"
  161: myStream.WriteText "##" & vbLf & _
  162:   "## Bundle of CA Root Certificates" & vbLf & _
  163:   "##" & vbLf & _
  164:   "## Certificate data from Mozilla as of: " & _
  165:     ConvertDateToString(LocalDateToUTC(Now)) & " GMT" & vbLf & _
  166:   "##" & vbLf & _
  167:   "## This is a bundle of X.509 certificates of public Certificate Authorities" & vbLf & _
  168:   "## (CA). These were automatically extracted from Mozilla's root certificates" & vbLf & _
  169:   "## file (certdata.txt).  This file can be found in the mozilla source tree:" & vbLf & _
  170:   "## " & myUrl & vbLf & _
  171:   "##" & vbLf & _
  172:   "## It contains the certificates in PEM format and therefore" & vbLf & _
  173:   "## can be directly used with curl / libcurl / php_curl, or with" & vbLf & _
  174:   "## an Apache+mod_ssl webserver for SSL client authentication." & vbLf & _
  175:   "## Just configure this file as the SSLCACertificateFile." & vbLf & _
  176:   "##" & vbLf & _
  177:   "## Conversion done with mk-ca-bundle.vbs version " & myVersion & "." & vbLf
  178: If (myCdSavF = TRUE) And (myUseOpenSSL = TRUE) Then
  179:   myStream.WriteText "## SHA256: " & FileSHA256(myCdFile) & vbLf
  180: End If
  181: myStream.WriteText "##" & vbLf & vbLf
  182: 
  183: myStream.WriteText vbLf
  184: For i = 0 To UBound(myLines)
  185:   If InstrRev(myLines(i), "CKA_LABEL ") Then
  186:     myPattern = "^CKA_LABEL\s+[A-Z0-9]+\s+""(.+?)"""
  187:     myLabel = RegExprFirst(myPattern, myLines(i))
  188:   End If
  189:   If (myInsideCert = TRUE) Then
  190:     If InstrRev(myLines(i), "END") Then
  191:       myInsideCert = FALSE
  192:       While (i < UBound(myLines)) And Not (myLines(i) = "#")
  193:         i = i + 1
  194:         If InstrRev(myLines(i), "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR") Then
  195:           myUntrusted = FALSE
  196:         End If
  197:       Wend
  198:       If (myUntrusted = TRUE) Then
  199:         myNumSkipped = myNumSkipped + 1
  200:       Else
  201:         myStream.WriteText myLabel & vbLf
  202:         myStream.WriteText String(Len(myLabel), "=") & vbLf
  203:         myPem = "-----BEGIN CERTIFICATE-----" & vbLf & _
  204:                 Base64Encode(myData) & vbLf & _
  205:                 "-----END CERTIFICATE-----" & vbLf
  206:         If (myOptTxt = FALSE) Then
  207:           myStream.WriteText myPem & vbLf
  208:         Else
  209:           Dim myCmd, myRval, myTmpIn, myTmpOut
  210:           myTmpIn = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
  211:           myTmpOut = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
  212:           Set myTmpFh = objFSO.OpenTextFile(myTmpIn, 2, TRUE)
  213:           myTmpFh.Write myPem
  214:           myTmpFh.Close
  215:           myCmd = """" & myOpenSSL & """ x509 -md5 -fingerprint -text " & _
  216:                   "-inform PEM -in " & myTmpIn & " -out " & myTmpOut
  217:           myRval = objShell.Run (myCmd, 0, TRUE)
  218:           objFSO.DeleteFile myTmpIn, TRUE
  219:           If Not (myRval = 0) Then
  220:             MsgBox("Failed to process PEM cert with OpenSSL commandline!"), vbCritical, mySelf
  221:             objFSO.DeleteFile myTmpOut, TRUE
  222:             WScript.Quit 3
  223:           End If
  224:           Set myTmpFh = objFSO.OpenTextFile(myTmpOut, 1)
  225:           myStream.WriteText myTmpFh.ReadAll & vbLf
  226:           myTmpFh.Close
  227:           objFSO.DeleteFile myTmpOut, TRUE
  228:         End If
  229:         myNumCerts = myNumCerts + 1
  230:       End If
  231:     Else
  232:       myOctets = Split(myLines(i), "\")
  233:       For j = 1 To UBound(myOctets)
  234:         myData = myData & Chr(CByte("&o" & myOctets(j)))
  235:       Next
  236:     End If
  237:   End If
  238:   If InstrRev(myLines(i), "CVS_ID ") Then
  239:     myPattern = "^CVS_ID\s+""(.+?)"""
  240:     myRev = RegExprFirst(myPattern, myLines(i))
  241:     myStream.WriteText "# " & myRev & vbLf & vbLf
  242:   End If
  243:   If InstrRev(myLines(i), "CKA_VALUE MULTILINE_OCTAL") Then
  244:     myInsideCert = TRUE
  245:     myUntrusted = TRUE
  246:     myData = ""
  247:   End If
  248:   If InstrRev(myLines(i), "***** BEGIN LICENSE BLOCK *****") Then
  249:     myInsideLicense = TRUE
  250:   End If
  251:   If (myInsideLicense = TRUE) Then
  252:     myStream.WriteText myLines(i) & vbLf
  253:     myLicenseText = myLicenseText & Mid(myLines(i), 2) & vbLf
  254:   End If
  255:   If InstrRev(myLines(i), "***** END LICENSE BLOCK *****") Then
  256:     myInsideLicense = FALSE
  257:     If (myAskLiF = TRUE) Then
  258:       If Not (6 = objShell.PopUp(myLicenseText & vbLf & _
  259:               "Do you agree to the license shown above (required to proceed) ?",, _
  260:               mySelf, vbQuestion + vbYesNo + vbDefaultButton1)) Then
  261:         myStream.Close
  262:         objFSO.DeleteFile myCaFile, TRUE
  263:         WScript.Quit 2
  264:       End If
  265:     End If
  266:   End If
  267: Next
  268: 
  269: ' To stop the UTF-8 BOM from being written the stream has to be copied and
  270: ' then saved as binary.
  271: Dim myCopy
  272: Set myCopy = CreateObject("ADODB.Stream")
  273: myCopy.Type = adTypeBinary
  274: myCopy.Open
  275: myStream.Position = 3 ' Skip UTF-8 BOM
  276: myStream.CopyTo myCopy
  277: myCopy.SaveToFile myCaFile, adSaveCreateOverWrite
  278: myCopy.Close
  279: myStream.Close
  280: Set myCopy = Nothing
  281: Set myStream = Nothing
  282: 
  283: ' Done
  284: objShell.PopUp "Done (" & myNumCerts & " CA certs processed, " & myNumSkipped & _
  285:                " untrusted skipped).", 20, mySelf, vbInformation
  286: WScript.Quit 0
  287: 
  288: Function ConvertBinaryToUTF8(arrBytes)
  289:   Dim objStream
  290:   Set objStream = CreateObject("ADODB.Stream")
  291:   objStream.Open
  292:   objStream.Type = adTypeBinary
  293:   objStream.Write arrBytes
  294:   objStream.Position = 0
  295:   objStream.Type = adTypeText
  296:   objStream.Charset = "utf-8"
  297:   ConvertBinaryToUTF8 = objStream.ReadText
  298:   Set objStream = Nothing
  299: End Function
  300: 
  301: Function SaveBinaryData(filename, data)
  302:   Dim objStream
  303:   Set objStream = CreateObject("ADODB.Stream")
  304:   objStream.Type = adTypeBinary
  305:   objStream.Open
  306:   objStream.Write data
  307:   objStream.SaveToFile filename, adSaveCreateOverWrite
  308:   objStream.Close
  309:   Set objStream = Nothing
  310: End Function
  311: 
  312: Function RegExprFirst(SearchPattern, TheString)
  313:   Dim objRegExp, Matches                        ' create variables.
  314:   Set objRegExp = New RegExp                    ' create a regular expression.
  315:   objRegExp.Pattern = SearchPattern             ' sets the search pattern.
  316:   objRegExp.IgnoreCase = TRUE                   ' set to ignores case.
  317:   objRegExp.Global = TRUE                       ' set to global search.
  318:   Set Matches = objRegExp.Execute(TheString)    ' do the search.
  319:   If (Matches.Count) Then
  320:     RegExprFirst = Matches(0).SubMatches(0)     ' return first match.
  321:   Else
  322:     RegExprFirst = ""
  323:   End If
  324:   Set objRegExp = Nothing
  325: End Function
  326: 
  327: Function Base64Encode(inData)
  328:   Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  329:   Dim cOut, sOut, lWrap, I
  330:   lWrap = Int(myWrapLe * 3 / 4)
  331: 
  332:   'For each group of 3 bytes
  333:   For I = 1 To Len(inData) Step 3
  334:     Dim nGroup, pOut, sGroup
  335: 
  336:     'Create one long from this 3 bytes.
  337:     nGroup = &H10000 * Asc(Mid(inData, I, 1)) + _
  338:              &H100 * MyASC(Mid(inData, I + 1, 1)) + _
  339:              MyASC(Mid(inData, I + 2, 1))
  340: 
  341:     'Oct splits the long To 8 groups with 3 bits
  342:     nGroup = Oct(nGroup)
  343: 
  344:     'Add leading zeros
  345:     nGroup = String(8 - Len(nGroup), "0") & nGroup
  346: 
  347:     'Convert To base64
  348:     pOut = Mid(Base64, CLng("&o" & Mid(nGroup, 1, 2)) + 1, 1) & _
  349:            Mid(Base64, CLng("&o" & Mid(nGroup, 3, 2)) + 1, 1) & _
  350:            Mid(Base64, CLng("&o" & Mid(nGroup, 5, 2)) + 1, 1) & _
  351:            Mid(Base64, CLng("&o" & Mid(nGroup, 7, 2)) + 1, 1)
  352: 
  353:     'Add the part To OutPut string
  354:     sOut = sOut + pOut
  355: 
  356:     'Add a new line For Each myWrapLe chars In dest
  357:     If (I < Len(inData) - 2) Then
  358:       If (I + 2) Mod lWrap = 0 Then sOut = sOut & vbLf
  359:     End If
  360:   Next
  361:   Select Case Len(inData) Mod 3
  362:     Case 1: '8 bit final
  363:       sOut = Left(sOut, Len(sOut) - 2) & "=="
  364:     Case 2: '16 bit final
  365:       sOut = Left(sOut, Len(sOut) - 1) & "="
  366:   End Select
  367:   Base64Encode = sOut
  368: End Function
  369: 
  370: Function MyASC(OneChar)
  371:   If OneChar = "" Then MyASC = 0 Else MyASC = Asc(OneChar)
  372: End Function
  373: 
  374: ' Return the date in the same format as perl to match mk-ca-bundle.pl output:
  375: ' Wed Sep  7 03:12:05 2016
  376: Function ConvertDateToString(input)
  377:   Dim output
  378:   output = WeekDayName(WeekDay(input), TRUE) & " " & _
  379:            MonthName(Month(input), TRUE) & " "
  380:   If (Len(Day(input)) = 1) Then
  381:     output = output & " "
  382:   End If
  383:   output = output & _
  384:            Day(input) & " " & _
  385:            FormatDateTime(input, vbShortTime) & ":"
  386:   If (Len(Second(input)) = 1) Then
  387:     output = output & "0"
  388:   End If
  389:   output = output & _
  390:            Second(input) & " " & _
  391:            Year(input)
  392:   ConvertDateToString = output
  393: End Function
  394: 
  395: ' Convert local Date to UTC. Microsoft says:
  396: ' Use Win32_ComputerSystem CurrentTimeZone property, because it automatically
  397: ' adjusts the Time Zone bias for daylight saving time; Win32_Time Zone Bias
  398: ' property does not.
  399: ' https://msdn.microsoft.com/en-us/library/windows/desktop/ms696015.aspx
  400: Function LocalDateToUTC(localdate)
  401:   Dim item, offset
  402:   For Each item In GetObject("winmgmts:").InstancesOf("Win32_ComputerSystem")
  403:     offset = item.CurrentTimeZone ' the offset in minutes
  404:   Next
  405:   If (offset < 0) Then
  406:     LocalDateToUTC = DateAdd("n",  ABS(offset), localdate)
  407:   Else
  408:     LocalDateToUTC = DateAdd("n", -ABS(offset), localdate)
  409:   End If
  410:   'objShell.PopUp LocalDateToUTC
  411: End Function
  412: 
  413: Function FileSHA256(filename)
  414:   Dim cmd, rval, tmpOut, tmpFh
  415:   if (myUseOpenSSL = TRUE) Then
  416:     tmpOut = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
  417:     cmd = """" & myOpenSSL & """ dgst -r -sha256 -out """ & tmpOut & """ """ & filename & """"
  418:     rval = objShell.Run(cmd, 0, TRUE)
  419:     If Not (rval = 0) Then
  420:       MsgBox("Failed to get sha256 of """ & filename & """ with OpenSSL commandline!"), vbCritical, mySelf
  421:       objFSO.DeleteFile tmpOut, TRUE
  422:       WScript.Quit 3
  423:     End If
  424:     Set tmpFh = objFSO.OpenTextFile(tmpOut, 1)
  425:     FileSHA256 = RegExprFirst("^([0-9a-f]{64}) .+", tmpFh.ReadAll)
  426:     tmpFh.Close
  427:     objFSO.DeleteFile tmpOut, TRUE
  428:   Else
  429:     FileSHA256 = ""
  430:   End If
  431: End Function

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>