summaryrefslogtreecommitdiff
path: root/build/pgo/genpgocert.py
diff options
context:
space:
mode:
Diffstat (limited to 'build/pgo/genpgocert.py')
-rw-r--r--build/pgo/genpgocert.py192
1 files changed, 192 insertions, 0 deletions
diff --git a/build/pgo/genpgocert.py b/build/pgo/genpgocert.py
new file mode 100644
index 0000000000..c58bcd40d6
--- /dev/null
+++ b/build/pgo/genpgocert.py
@@ -0,0 +1,192 @@
+#!/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)