123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- #!/usr/bin/env python
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- # This script exists to generate the Certificate Authority and server
- # certificates used for SSL testing in Mochitest. The already generated
- # certs are located at $topsrcdir/build/pgo/certs/ .
- import mozinfo
- import os
- import random
- import re
- import shutil
- import subprocess
- import sys
- import tempfile
- from mozbuild.base import MozbuildObject
- from mozfile import NamedTemporaryFile
- from mozprofile.permissions import ServerLocations
- dbFiles = [
- re.compile("^cert[0-9]+\.db$"),
- re.compile("^key[0-9]+\.db$"),
- re.compile("^secmod\.db$")
- ]
- def unlinkDbFiles(path):
- for root, dirs, files in os.walk(path):
- for name in files:
- for dbFile in dbFiles:
- if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
- os.unlink(os.path.join(root, name))
- def dbFilesExist(path):
- for root, dirs, files in os.walk(path):
- for name in files:
- for dbFile in dbFiles:
- if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
- return True
- return False
- def runUtil(util, args, inputdata = None):
- env = os.environ.copy()
- if mozinfo.os == "linux":
- pathvar = "LD_LIBRARY_PATH"
- app_path = os.path.dirname(util)
- if pathvar in env:
- env[pathvar] = "%s%s%s" % (app_path, os.pathsep, env[pathvar])
- else:
- env[pathvar] = app_path
- proc = subprocess.Popen([util] + args, env=env,
- stdin=subprocess.PIPE if inputdata else None)
- proc.communicate(inputdata)
- return proc.returncode
- def createRandomFile(randomFile):
- for count in xrange(0, 2048):
- randomFile.write(chr(random.randint(0, 255)))
- def createCertificateAuthority(build, srcDir):
- certutil = build.get_binary_path(what="certutil")
- pk12util = build.get_binary_path(what="pk12util")
- #TODO: mozfile.TemporaryDirectory
- tempDbDir = tempfile.mkdtemp()
- with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
- pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
- pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
- pwfile.write("\n")
- # Create temporary certification database for CA generation
- status = runUtil(certutil, ["-N", "-d", tempDbDir, "-f", pwfile.name])
- if status:
- return status
- createRandomFile(rndfile)
- status = runUtil(certutil, ["-S", "-d", tempDbDir, "-s", "CN=Temporary Certificate Authority, O=Mozilla Testing, OU=Profile Guided Optimization", "-t", "C,,", "-x", "-m", "1", "-v", "120", "-n", "pgo temporary ca", "-2", "-f", pwfile.name, "-z", rndfile.name], "Y\n0\nN\n")
- if status:
- return status
- status = runUtil(certutil, ["-L", "-d", tempDbDir, "-n", "pgo temporary ca", "-a", "-o", pgoCAPathSrc, "-f", pwfile.name])
- if status:
- return status
- status = runUtil(pk12util, ["-o", pgoCAModulePathSrc, "-n", "pgo temporary ca", "-d", tempDbDir, "-w", pwfile.name, "-k", pwfile.name])
- if status:
- return status
- shutil.rmtree(tempDbDir)
- return 0
- def createSSLServerCertificate(build, srcDir):
- certutil = build.get_binary_path(what="certutil")
- pk12util = build.get_binary_path(what="pk12util")
- with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
- pgoCAPath = os.path.join(srcDir, "pgoca.p12")
- pwfile.write("\n")
- if not dbFilesExist(srcDir):
- # Make sure all DB files from src are really deleted
- unlinkDbFiles(srcDir)
- # Create certification database for ssltunnel
- status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfile.name])
- if status:
- return status
- status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfile.name, "-d", srcDir, "-k", pwfile.name])
- if status:
- return status
- # Generate automatic certificate
- locations = ServerLocations(os.path.join(build.topsrcdir,
- "build", "pgo",
- "server-locations.txt"))
- iterator = iter(locations)
- # Skips the first entry, I don't know why: bug 879740
- iterator.next()
- locationsParam = ""
- firstLocation = ""
- for loc in iterator:
- if loc.scheme == "https" and "nocert" not in loc.options:
- customCertOption = False
- customCertRE = re.compile("^cert=(?:\w+)")
- for option in loc.options:
- match = customCertRE.match(option)
- if match:
- customCertOption = True
- break
- if not customCertOption:
- if len(locationsParam) > 0:
- locationsParam += ","
- locationsParam += loc.host
- if firstLocation == "":
- firstLocation = loc.host
- if not firstLocation:
- print "Nothing to generate, no automatic secure hosts specified"
- else:
- createRandomFile(rndfile)
- runUtil(certutil, ["-D", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
- # Ignore the result, the certificate may not be present when new database is being built
- status = runUtil(certutil, ["-S", "-s", "CN=%s" % firstLocation, "-t", "Pu,,", "-c", "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v", "120", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
- if status:
- return status
- return 0
- if len(sys.argv) == 1:
- print "Specify --gen-server or --gen-ca"
- sys.exit(1)
- build = MozbuildObject.from_environment()
- certdir = os.path.join(build.topsrcdir, "build", "pgo", "certs")
- if sys.argv[1] == "--gen-server":
- certificateStatus = createSSLServerCertificate(build, certdir)
- if certificateStatus:
- print "TEST-UNEXPECTED-FAIL | SSL Server Certificate generation"
- sys.exit(certificateStatus)
- if sys.argv[1] == "--gen-ca":
- certificateStatus = createCertificateAuthority(build, certdir)
- if certificateStatus:
- print "TEST-UNEXPECTED-FAIL | Certificate Authority generation"
- else:
- print "\n\n"
- print "==================================================="
- print " IMPORTANT:"
- print " To use this new certificate authority in tests"
- print " run 'make' at testing/mochitest"
- print "==================================================="
- sys.exit(certificateStatus)
- print "Invalid option specified"
- sys.exit(1)
|