https://github.com/mozilla/gecko-dev
Raw File
Tip revision: b632b2878b9aa2237bca9e79624e8e29b24a1afa authored by tbirdbld on 25 August 2012, 00:10:40 UTC
Added THUNDERBIRD_15_0_RELEASE THUNDERBIRD_15_0_BUILD1 tag(s) for changeset 28af55043104. DONTBUILD CLOSED TREE a=release
Tip revision: b632b28
genpgocert.py.in
#
# 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/.

from automation import Automation
import os
import re
import shutil
import sys

#expand DIST_BIN = __XPC_BIN_PATH__
#expand BIN_SUFFIX = __BIN_SUFFIX__
#expand PROFILE_DIR = __PROFILE_DIR__
#expand CERTS_SRC_DIR = __CERTS_SRC_DIR__

automation = Automation()

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):
  if inputdata:
    proc = automation.Process([util] + args, env = automation.environment(), stdin = automation.PIPE)
    proc.communicate(inputdata)
    return proc.returncode
  return automation.Process([util] + args, env = automation.environment()).wait()


def createRandomFile(randomFile):
  import random
  file = open(randomFile, "wb");
  for count in xrange(0, 2048):
    file.write(chr(random.randint(0, 255)))
  file.close()


def createCertificateAuthority(profileDir, srcDir):
  certutil = DIST_BIN + "/certutil" + BIN_SUFFIX
  pk12util = DIST_BIN + "/pk12util" + BIN_SUFFIX

  tempDbDir = os.path.join(profileDir, ".temp")
  if not os.path.exists(tempDbDir):
    os.mkdir(tempDbDir)
  
  pwfilePath = os.path.join(tempDbDir, ".crtdbpw")
  rndfilePath = os.path.join(tempDbDir, ".rndfile")
  pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
  pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
  
  pwfile = open(pwfilePath, "w")
  pwfile.write("\n")
  pwfile.close()

  unlinkDbFiles(tempDbDir)

  # Create temporary certification database for CA generation
  status = runUtil(certutil, ["-N", "-d", tempDbDir, "-f", pwfilePath])
  if status != 0:
    return status

  createRandomFile(rndfilePath);
  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", pwfilePath, "-z", rndfilePath], "Y\n0\nN\n")
  if status != 0:
    return status
 
  status = runUtil(certutil, ["-L", "-d", tempDbDir, "-n", "pgo temporary ca", "-a", "-o", pgoCAPathSrc, "-f", pwfilePath])
  if status != 0:
    return status
 
  status = runUtil(pk12util, ["-o", pgoCAModulePathSrc, "-n", "pgo temporary ca", "-d", tempDbDir, "-w", pwfilePath, "-k", pwfilePath])
  if status != 0:
    return status
    
  unlinkDbFiles(tempDbDir)
  os.unlink(pwfilePath)
  os.unlink(rndfilePath)
  os.rmdir(tempDbDir)
  return 0


def createSSLServerCertificate(profileDir, srcDir):
  certutil = DIST_BIN + "/certutil" + BIN_SUFFIX
  pk12util = DIST_BIN + "/pk12util" + BIN_SUFFIX

  pwfilePath = os.path.join(profileDir, ".crtdbpw")
  rndfilePath = os.path.join(profileDir, ".rndfile")
  pgoCAPath = os.path.join(srcDir, "pgoca.p12")
  
  pwfile = open(pwfilePath, "w")
  pwfile.write("\n")
  pwfile.close()

  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", pwfilePath])
    if status != 0:
      return status
  
    status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfilePath, "-d", srcDir, "-k", pwfilePath])
    if status != 0:
      return status

  # Generate automatic certificate
  locations = automation.readLocations(os.path.join(profileDir, "server-locations.txt"))
  locations.pop(0)
  locationsParam = ""
  firstLocation = ""
  for loc in locations:
    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 firstLocation == "":
    print "Nothing to generate, no automatic secure hosts specified"
  else:
    createRandomFile(rndfilePath);
    
    runUtil(certutil, ["-D", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfilePath, "-f", pwfilePath])
    # 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", rndfilePath, "-f", pwfilePath])
    if status != 0:
      return status
    
  os.unlink(pwfilePath)
  os.unlink(rndfilePath)
  return 0


if len(sys.argv) == 1:
  print "Specify --gen-server or --gen-ca"
  sys.exit(1)

if sys.argv[1] == "--gen-server":
  certificateStatus = createSSLServerCertificate(PROFILE_DIR, CERTS_SRC_DIR)
  if certificateStatus != 0:
    print "TEST-UNEXPECTED-FAIL | SSL Server Certificate generation"
  
  sys.exit(certificateStatus)
  
if sys.argv[1] == "--gen-ca":
  certificateStatus = createCertificateAuthority(PROFILE_DIR, CERTS_SRC_DIR)
  if certificateStatus != 0:
    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)
back to top