Backed out changeset 3770c42e3118

This commit is contained in:
Kai Engert 2008-08-16 08:00:17 +02:00
Родитель b7d44caf95
Коммит 54d46c6523
13 изменённых файлов: 116 добавлений и 938 удалений

Просмотреть файл

@ -79,13 +79,9 @@ browser_path = \"$(DIST)/bin/$(PROGRAM)\"
endif endif
endif endif
_CERTS_DIR = _profile/pgo/certs
AUTOMATION_PPARGS = \ AUTOMATION_PPARGS = \
-DBROWSER_PATH=$(browser_path) \ -DBROWSER_PATH=$(browser_path) \
-DXPC_BIN_PATH=\"$(DIST)/bin\" \ -DXPC_BIN_PATH=\"$(DIST)/bin\" \
-DBIN_SUFFIX=\"$(BIN_SUFFIX)\" \
-DCERTS_DIR=\"../$(_CERTS_DIR)\" \
$(NULL) $(NULL)
ifeq ($(OS_ARCH),Darwin) ifeq ($(OS_ARCH),Darwin)

Просмотреть файл

@ -43,27 +43,20 @@ VPATH = @srcdir@
relativesrcdir = build/pgo relativesrcdir = build/pgo
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
DIRS = \
certs \
$(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
# Stuff to make a build with a profile # Stuff to make a build with a profile
_PROFILE_DIR = $(DEPTH)/_profile/pgo _PROFILE_DIR = $(DEPTH)/_profile/pgo
_CERTS_DIR = $(_PROFILE_DIR)/certs
_CERTS_SRC_DIR = $(srcdir)/certs
_PGO_FILES = \ _PGO_FILES = \
automation.py \ automation.py \
profileserver.py \ profileserver.py \
genpgocert.py \
index.html \ index.html \
quit.js \ quit.js \
server-locations.txt \ server-locations.txt \
$(NULL) $(NULL)
ifeq ($(USE_SHORT_LIBNAME), 1) ifeq ($(USE_SHORT_LIBNAME), 1)
PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX) PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
else else
@ -87,9 +80,6 @@ endif
AUTOMATION_PPARGS = \ AUTOMATION_PPARGS = \
-DBROWSER_PATH=$(browser_path) \ -DBROWSER_PATH=$(browser_path) \
-DXPC_BIN_PATH=\"$(DIST)/bin\" \ -DXPC_BIN_PATH=\"$(DIST)/bin\" \
-DBIN_SUFFIX=\"$(BIN_SUFFIX)\" \
-DCERTS_DIR=\"$(_CERTS_DIR)\" \
-DCERTS_SRC_DIR=\"$(_CERTS_SRC_DIR)\" \
$(NULL) $(NULL)
ifeq ($(OS_ARCH),Darwin) ifeq ($(OS_ARCH),Darwin)
@ -112,15 +102,11 @@ automation.py: automation.py.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \ $(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@ $(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@
genpgocert.py: genpgocert.py.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@
profileserver.py: profileserver.py.in profileserver.py: profileserver.py.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $^ > $@ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $^ > $@
chmod +x $@ chmod +x $@
GARBAGE += automation.py profileserver.py genpgocert.py GARBAGE += automation.py profileserver.py
libs:: $(_PGO_FILES) libs:: $(_PGO_FILES)
$(INSTALL) $^ $(_PROFILE_DIR) $(INSTALL) $^ $(_PROFILE_DIR)

Просмотреть файл

@ -74,12 +74,10 @@ __all__ = [
IS_CYGWIN = False IS_CYGWIN = False
#endif #endif
#expand IS_CAMINO = __IS_CAMINO__ != 0 #expand IS_CAMINO = __IS_CAMINO__ != 0
#expand BIN_SUFFIX = __BIN_SUFFIX__
UNIXISH = not IS_WIN32 and not IS_MAC UNIXISH = not IS_WIN32 and not IS_MAC
#expand DEFAULT_APP = "./" + __BROWSER_PATH__ #expand DEFAULT_APP = "./" + __BROWSER_PATH__
#expand CERTS_DIR = __CERTS_DIR__
########### ###########
# LOGGING # # LOGGING #
@ -105,7 +103,7 @@ class Process:
non-Windows platforms. :-( non-Windows platforms. :-(
""" """
def __init__(self, command, args, env, inputdata = None): def __init__(self, command, args, env):
""" """
Creates a process representing the execution of the given command, which Creates a process representing the execution of the given command, which
must be an absolute path, with the given arguments in the given environment. must be an absolute path, with the given arguments in the given environment.
@ -113,40 +111,24 @@ class Process:
""" """
command = os.path.abspath(command) command = os.path.abspath(command)
if IS_WIN32: if IS_WIN32:
import tempfile
import subprocess import subprocess
if inputdata:
inputfile = tempfile.TemporaryFile()
inputfile.write(inputdata)
inputfile.seek(0)
else:
inputfile = None
cmd = [command] cmd = [command]
cmd.extend(args) cmd.extend(args)
p = subprocess.Popen(cmd, env = env, p = subprocess.Popen(cmd, env = env,
stdout = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = subprocess.STDOUT, stderr = subprocess.STDOUT)
stdin = inputfile)
self._out = p.stdout self._out = p.stdout
else: else:
import popen2 import popen2
cmd = [] cmd = []
if env: for (k, v) in env.iteritems():
for (k, v) in env.iteritems(): cmd.append(k + "='" + v + "' ")
cmd.append(k + "='" + v + "' ")
cmd.append("'" + command + "'") cmd.append("'" + command + "'")
cmd.extend(map(lambda x: "'" + x + "'", args)) cmd.extend(map(lambda x: "'" + x + "'", args))
cmd = " ".join(cmd) cmd = " ".join(cmd)
p = popen2.Popen4(cmd) p = popen2.Popen4(cmd)
self._out = p.fromchild self._out = p.fromchild
if inputdata:
p.tochild.write(inputdata)
p.tochild.close()
self._process = p self._process = p
self.pid = p.pid self.pid = p.pid
@ -183,13 +165,8 @@ class Process:
def kill(self): def kill(self):
"Kills this process." "Kills this process."
try: try:
if not IS_WIN32: if not IS_WIN32: # XXX
os.kill(self._process.pid, signal.SIGKILL) os.kill(self._process.pid, signal.SIGKILL)
else:
import subprocess
pid = "%i" % self.pid
process = subprocess.Popen(["taskkill", "/F", "/PID", pid])
process.wait()
except: except:
pass pass
@ -224,13 +201,13 @@ class Location:
self.options = options self.options = options
def readLocations(locationsPath = "server-locations.txt"): def readLocations():
""" """
Reads the locations at which the Mochitest HTTP server is available from Reads the locations at which the Mochitest HTTP server is available from
server-locations.txt. server-locations.txt.
""" """
locationFile = codecs.open(locationsPath, "r", "UTF-8") locationFile = codecs.open("server-locations.txt", "r", "UTF-8")
# Perhaps more detail than necessary, but it's the easiest way to make sure # Perhaps more detail than necessary, but it's the easiest way to make sure
# we get exactly the format we want. See server-locations.txt for the exact # we get exactly the format we want. See server-locations.txt for the exact
@ -247,7 +224,7 @@ def readLocations(locationsPath = "server-locations.txt"):
r"(?P<port>\d+)" r"(?P<port>\d+)"
r"(?:" r"(?:"
r"\s+" r"\s+"
r"(?P<options>\S+(?:,\S+)*)" r"(?P<options>\w+(?:,\w+)*)"
r")?$") r")?$")
locations = [] locations = []
lineno = 0 lineno = 0
@ -341,20 +318,13 @@ function FindProxyForURL(url, host)
if (!matches) if (!matches)
return 'DIRECT'; return 'DIRECT';
var isHttp = matches[1] == 'http'; var isHttp = matches[1] == 'http';
var isHttps = matches[1] == 'https';
if (!matches[3]) if (!matches[3])
{ matches[3] = isHttp ? '80' : '443';
if (isHttp) matches[3] = '80';
if (isHttps) matches[3] = '443';
}
var origin = matches[1] + '://' + matches[2] + ':' + matches[3]; var origin = matches[1] + '://' + matches[2] + ':' + matches[3];
if (origins.indexOf(origin) < 0) if (origins.indexOf(origin) < 0)
return 'DIRECT'; return 'DIRECT';
if (isHttp) if (isHttp)
return 'PROXY 127.0.0.1:8888'; return 'PROXY localhost:8888';
if (isHttps)
return 'PROXY 127.0.0.1:4443';
return 'DIRECT'; return 'DIRECT';
}""" % { "origins": origins } }""" % { "origins": origins }
pacURL = "".join(pacURL.splitlines()) pacURL = "".join(pacURL.splitlines())
@ -372,70 +342,12 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
prefsFile.write("".join(prefs)) prefsFile.write("".join(prefs))
prefsFile.close() prefsFile.close()
def fillCertificateDB(profileDir):
pwfilePath = os.path.join(profileDir, ".crtdbpw")
pwfile = open(pwfilePath, "w")
pwfile.write("\n")
pwfile.close()
# Create head of the ssltunnel configuration file
sslTunnelConfigPath = os.path.join(CERTS_DIR, "ssltunnel.cfg")
sslTunnelConfig = open(sslTunnelConfigPath, "w")
sslTunnelConfig.write("httpproxy:1\n")
sslTunnelConfig.write("certdbdir:%s\n" % CERTS_DIR)
sslTunnelConfig.write("forward:127.0.0.1:8888\n")
sslTunnelConfig.write("listen:*:4443:pgo server certificate\n")
# Generate automatic certificate and bond custom certificates
locations = readLocations()
locations.pop(0)
for loc in locations:
if loc.scheme == "https" and "nocert" not in loc.options:
customCertRE = re.compile("^cert=(?P<nickname>[0-9a-zA-Z_ ]+)")
for option in loc.options:
match = customCertRE.match(option)
if match:
customcert = match.group("nickname");
sslTunnelConfig.write("listen:%s:%s:4443:%s\n" % (loc.host, loc.port, customcert))
break
sslTunnelConfig.close()
# Pre-create the certification database for the profile
certutil = DIST_BIN + "/certutil" + BIN_SUFFIX
status = Process(certutil, ["-N", "-d", profileDir, "-f", pwfilePath], None).wait()
if status != 0:
return status
# Walk the cert directory and add custom CAs as trusted
files = os.listdir(CERTS_DIR)
for item in files:
root, ext = os.path.splitext(item)
if ext == ".ca":
Process(certutil, ["-A", "-i", os.path.join(CERTS_DIR, item), "-d", profileDir, "-f", pwfilePath, "-n", root, "-t", "CT,,"], None)
os.unlink(pwfilePath)
return 0
############### ###############
# RUN THE APP # # RUN THE APP #
############### ###############
def runApp(testURL, env, app, profileDir, extraArgs): def runApp(testURL, env, app, profileDir, extraArgs):
# create certificate database for the profile
certificateStatus = fillCertificateDB(profileDir)
if certificateStatus != 0:
log.info("ERROR FAIL Certificate integration")
return certificateStatus
ssltunnel = DIST_BIN + "/ssltunnel" + BIN_SUFFIX
ssltunnelProcess = Process(ssltunnel, [os.path.join(CERTS_DIR, "ssltunnel.cfg")], None)
log.info("SSL tunnel pid: %d", ssltunnelProcess.pid)
"Run the app, returning the time at which it was started." "Run the app, returning the time at which it was started."
# mark the start # mark the start
start = datetime.now() start = datetime.now()
@ -467,6 +379,4 @@ def runApp(testURL, env, app, profileDir, extraArgs):
if status != 0: if status != 0:
log.info("ERROR FAIL Exited with code %d during test run", status) log.info("ERROR FAIL Exited with code %d during test run", status)
ssltunnelProcess.kill()
return start return start

Просмотреть файл

@ -1,65 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla test code
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Honza Bambas <honzab@firemni.cz>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
_PROFILE_DIR = $(DEPTH)/_profile/pgo
_CERTS_DIR = $(_PROFILE_DIR)/certs
# Extension of files must be '.server'
_SERVER_CERTS = \
$(NULL)
# Extension of files must be '.ca'
_CERT_AUTHORITIES = \
pgoca.ca \
$(NULL)
_SERV_FILES = \
pgoca.p12 \
$(NULL)
include $(topsrcdir)/config/rules.mk
libs:: $(_SERV_FILES) $(_SERVER_CERTS) $(_CERT_AUTHORITIES)
$(INSTALL) $^ $(_CERTS_DIR)

Просмотреть файл

@ -1,15 +0,0 @@
-----BEGIN CERTIFICATE-----
MIICXTCCAcagAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMSQwIgYDVQQLExtQcm9m
aWxlIEd1aWRlZCBPcHRpbWl6YXRpb24xGDAWBgNVBAoTD01vemlsbGEgVGVzdGlu
ZzEoMCYGA1UEAxMfVGVtcG9yYXJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0w
ODA1MjIwMDM4MDVaFw0xODA1MjIwMDM4MDVaMGoxJDAiBgNVBAsTG1Byb2ZpbGUg
R3VpZGVkIE9wdGltaXphdGlvbjEYMBYGA1UEChMPTW96aWxsYSBUZXN0aW5nMSgw
JgYDVQQDEx9UZW1wb3JhcnkgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqG
SIb3DQEBAQUAA4GNADCBiQKBgQDg6iipAXGZYmgTcHfx8M2hcLqmqDalcj7sZ1A7
a3LiCBb+1uHKKy9hUxRUe61aJF4NgMAF5oc+HpXN0hpvkiNHxqqD7R6hrkP3gAJ3
eczEFKsFUI6AqaCL0+xpyhaaZmmarcHxU+PL2h5zq6VssxfBAsO0DkzWzk6E8vM+
jrku7QIDAQABoxMwETAPBgNVHRMECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GB
ALPbn3Ztg0m8qDt8Vkf5You6HEqIxZe+ffDTrfq/L7ofHk/OXEpL7OWKRHU33pNG
QS8khBG+sO461C51s6u9giW+eq2PaQv2HGASBpDbvPqc/Hf+zupZsdsXzHv6rt0V
lu5B6nOpMse1nhA494i1ARSuBNzLv5mas38YWG8Rr6jR
-----END CERTIFICATE-----

Двоичные данные
build/pgo/certs/pgoca.p12

Двоичный файл не отображается.

Просмотреть файл

@ -1,217 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Honza Bambas <honzab@firemni.cz>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import automation
import os
import re
import sys
#expand DIST_BIN = "./" + __XPC_BIN_PATH__
#expand BIN_SUFFIX = __BIN_SUFFIX__
#expand CERTS_DIR = __CERTS_DIR__
#expand CERTS_SRC_DIR = __CERTS_SRC_DIR__
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
dbFiles = ["cert8.db", "cert9.db", "key3.db", "key4.db", "secmod.db"]
def dbPaths(dir):
return map(lambda f: os.path.join(dir, f), dbFiles)
def runUtil(util, args, inputdata = None):
myEnvironment = dict(os.environ)
if automation.UNIXISH:
myEnvironment["LD_LIBRARY_PATH"] = os.path.join(SCRIPT_DIR, automation.DIST_BIN)
proc = automation.Process(util, args, myEnvironment, inputdata)
return proc.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(dbDir, srcDir):
certutil = DIST_BIN + "/certutil" + BIN_SUFFIX
pk12util = DIST_BIN + "/pk12util" + BIN_SUFFIX
tempDbDir = os.path.join(dbDir, ".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")
pgoCAModulePath = os.path.join(srcDir, "pgoca.p12")
pgoCAPath = os.path.join(srcDir, "pgoca.ca")
pwfile = open(pwfilePath, "w")
pwfile.write("\n")
pwfile.close()
for dbFile in dbPaths(tempDbDir):
if os.path.exists(dbFile):
os.unlink(dbFile)
# 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
for dbFile in dbPaths(tempDbDir):
if os.path.exists(dbFile):
os.unlink(dbFile)
os.unlink(pwfilePath)
os.unlink(rndfilePath)
os.rmdir(tempDbDir)
return 0
def createSSLServerCertificate(dbDir):
certutil = DIST_BIN + "/certutil" + BIN_SUFFIX
pk12util = DIST_BIN + "/pk12util" + BIN_SUFFIX
pwfilePath = os.path.join(dbDir, ".crtdbpw")
rndfilePath = os.path.join(dbDir, ".rndfile")
pgoCAPath = os.path.join(dbDir, "pgoca.p12")
pwfile = open(pwfilePath, "w")
pwfile.write("\n")
pwfile.close()
for dbFile in dbPaths(dbDir):
if os.path.exists(dbFile):
os.unlink(dbFile)
# Create certification database for ssltunnel
status = runUtil(certutil, ["-N", "-d", dbDir, "-f", pwfilePath])
if status != 0:
return status
status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfilePath, "-d", dbDir, "-k", pwfilePath])
if status != 0:
return status
# Generate automatic certificate
locations = automation.readLocations(os.path.join(dbDir, "../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);
status = runUtil(certutil, ["-S", "-s", "CN=%s" % firstLocation, "-t", "Pu,,", "-c", "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v", "12", "-n", "pgo server certificate", "-d", dbDir, "-z", rndfilePath, "-f", pwfilePath])
if status != 0:
return status
# Walk the cert directory and add what necessary
files = os.listdir(CERTS_DIR)
for item in files:
root, ext = os.path.splitext(item)
if ext == ".server":
runUtil(pk12util, ["-i", os.path.join(CERTS_DIR, item), "-d", dbDir, "-k", pwfilePath, "-w", pwfilePath])
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(CERTS_DIR)
if certificateStatus != 0:
print "ERROR FAIL: SSL Server Certificate generation"
sys.exit(certificateStatus)
if sys.argv[1] == "--gen-ca":
certificateStatus = createCertificateAuthority(CERTS_DIR, CERTS_SRC_DIR)
if certificateStatus != 0:
print "ERROR 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)

Просмотреть файл

@ -52,24 +52,11 @@
# number is the default for the protocol. # number is the default for the protocol.
# #
# Unrecognized options are ignored. Recognized options are "primary" and # Unrecognized options are ignored. Recognized options are "primary" and
# "privileged", "nocert", "cert=some_cert_nickname". # "privileged". "primary" denotes a location which is the canonical location of
#
# "primary" denotes a location which is the canonical location of
# the server; this location is the one assumed for requests which don't # the server; this location is the one assumed for requests which don't
# otherwise identify a particular origin (e.g. HTTP/1.0 requests). # otherwise identify a particular origin (e.g. HTTP/1.0 requests). "privileged"
# # denotes a location which should have the ability to request elevated
# "privileged" denotes a location which should have the ability to request # privileges; the default is no privileges.
# elevated privileges; the default is no privileges.
#
# "nocert" makes sense only for https:// hosts and means there is not
# any certificate automatically generated for this host.
#
# "cert=nickname" tells the pgo server to use a particular certificate
# for this host. The certificate is referenced by its nickname that must
# not contain any spaces. The certificate key files (PKCS12 modules)
# for custom certification are loaded from build/pgo/ssltunnel/certs
# directory. When new certificate is added to this dir pgo/ssltunnel
# must be builded then.
# #
# #
@ -103,15 +90,6 @@ http://sub1.test2.example.com:80 privileged
http://sub2.test1.example.com:80 privileged http://sub2.test1.example.com:80 privileged
http://sub2.test2.example.com:80 privileged http://sub2.test2.example.com:80 privileged
https://example.com:443 privileged
https://test1.example.com:443 privileged
https://test2.example.com:443 privileged
https://sub1.test1.example.com:443 privileged
https://sub1.test2.example.com:443 privileged
https://sub2.test1.example.com:443 privileged
https://sub2.test2.example.com:443 privileged
https://nocert.example.com:443 privileged,nocert
# #
# These are subdomains of <ält.example.org>. # These are subdomains of <ält.example.org>.
# #
@ -120,9 +98,6 @@ http://sub2.xn--lt-uia.example.org:80 privileged
http://xn--exmple-cua.test:80 privileged http://xn--exmple-cua.test:80 privileged
http://sub1.xn--exmple-cua.test:80 privileged http://sub1.xn--exmple-cua.test:80 privileged
https://xn--hxajbheg2az3al.xn--jxalpdlp:443 privileged
https://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:443 privileged
# #
# These are subdomains of <παράδειγμα.δοκιμή>, the Greek IDN for example.test. # These are subdomains of <παράδειγμα.δοκιμή>, the Greek IDN for example.test.
# #
@ -139,8 +114,3 @@ http://sectest1.example.org:80 privileged
http://sub.sectest2.example.org:80 privileged http://sub.sectest2.example.org:80 privileged
http://sectest2.example.org:80 http://sectest2.example.org:80
http://sub.sectest1.example.org:80 http://sub.sectest1.example.org:80
https://sectest1.example.org:443 privileged
https://sub.sectest2.example.org:443 privileged
https://sectest2.example.org:443
https://sub.sectest1.example.org:443

Просмотреть файл

@ -281,16 +281,8 @@ ifndef MOZ_NATIVE_NSS
$(MAKE) -C $(topsrcdir)/security/coreconf $(DEFAULT_GMAKE_FLAGS) $(MAKE) -C $(topsrcdir)/security/coreconf $(DEFAULT_GMAKE_FLAGS)
$(MAKE) -C $(topsrcdir)/security/dbm $(DEFAULT_GMAKE_FLAGS) $(MAKE) -C $(topsrcdir)/security/dbm $(DEFAULT_GMAKE_FLAGS)
$(MAKE) -C $(topsrcdir)/security/nss/lib $(DEFAULT_GMAKE_FLAGS) $(MAKE) -C $(topsrcdir)/security/nss/lib $(DEFAULT_GMAKE_FLAGS)
ifdef ENABLE_TESTS
# Need certutil binary for mochitest certificates generation
$(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS)
$(MAKE) -C $(topsrcdir)/security/nss/cmd/certutil $(DEFAULT_GMAKE_FLAGS)
$(MAKE) -C $(topsrcdir)/security/nss/cmd/pk12util $(DEFAULT_GMAKE_FLAGS)
endif
ifndef SKIP_CHK ifndef SKIP_CHK
ifndef ENABLE_TESTS # Just avoid secondary compile
$(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS) $(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS)
endif
$(MAKE) -C $(topsrcdir)/security/nss/cmd/shlibsign $(DEFAULT_GMAKE_FLAGS) $(MAKE) -C $(topsrcdir)/security/nss/cmd/shlibsign $(DEFAULT_GMAKE_FLAGS)
endif endif
$(INSTALL) -m 755 $(DIST)/lib/$(LOADABLE_ROOT_MODULE) $(DIST)/bin $(INSTALL) -m 755 $(DIST)/lib/$(LOADABLE_ROOT_MODULE) $(DIST)/bin

Просмотреть файл

@ -74,7 +74,6 @@ _SERV_FILES = \
_DEST_DIR = $(DEPTH)/_tests/$(relativesrcdir) _DEST_DIR = $(DEPTH)/_tests/$(relativesrcdir)
_CERTS_DIR = $(DEPTH)/_profile/pgo/certs
ifeq ($(USE_SHORT_LIBNAME), 1) ifeq ($(USE_SHORT_LIBNAME), 1)
PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX) PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
@ -100,8 +99,6 @@ endif
TEST_DRIVER_PPARGS = \ TEST_DRIVER_PPARGS = \
-DBROWSER_PATH=$(browser_path) \ -DBROWSER_PATH=$(browser_path) \
-DXPC_BIN_PATH=\"../$(DIST)/bin\" \ -DXPC_BIN_PATH=\"../$(DIST)/bin\" \
-DBIN_SUFFIX=\"$(BIN_SUFFIX)\" \
-DCERTS_DIR=\"../$(_CERTS_DIR)\" \
$(NULL) $(NULL)
ifeq ($(OS_ARCH),Darwin) ifeq ($(OS_ARCH),Darwin)
@ -132,6 +129,3 @@ GARBAGE += runtests.py automation.py
libs:: $(_SERV_FILES) libs:: $(_SERV_FILES)
$(INSTALL) $^ $(_DEST_DIR) $(INSTALL) $^ $(_DEST_DIR)
libs::
$(PYTHON) $(DEPTH)/_profile/pgo/genpgocert.py --gen-server

Просмотреть файл

@ -222,7 +222,7 @@ function processLocations(server)
"(\\d+)" + "(\\d+)" +
"(?:" + "(?:" +
"\\s+" + "\\s+" +
"(\\S+(?:,\\S+)*)" + "(\\w+(?:,\\w+)*)" +
")?$"); ")?$");
var line = {}; var line = {};

Просмотреть файл

@ -50,7 +50,6 @@
#include "key.h" #include "key.h"
#include "keyt.h" #include "keyt.h"
#include "ssl.h" #include "ssl.h"
#include "plhash.h"
using std::string; using std::string;
using std::vector; using std::vector;
@ -58,8 +57,8 @@ using std::vector;
// Structs for passing data into jobs on the thread pool // Structs for passing data into jobs on the thread pool
typedef struct { typedef struct {
PRInt32 listen_port; PRInt32 listen_port;
PRNetAddr remote_addr;
string cert_nickname; string cert_nickname;
PLHashTable* host_cert_table;
} server_info_t; } server_info_t;
typedef struct { typedef struct {
@ -114,16 +113,11 @@ const PRInt32 DEFAULT_STACKSIZE = (512 * 1024);
const PRInt32 BUF_SIZE = 4096; const PRInt32 BUF_SIZE = 4096;
// global data // global data
string nssconfigdir;
vector<server_info_t> servers;
PRNetAddr remote_addr;
PRThreadPool* threads = NULL; PRThreadPool* threads = NULL;
PRLock* shutdown_lock = NULL; PRLock* shutdown_lock = NULL;
PRCondVar* shutdown_condvar = NULL; PRCondVar* shutdown_condvar = NULL;
// Not really used, unless something fails to start // Not really used, unless something fails to start
bool shutdown_server = false; bool shutdown_server = false;
bool do_http_proxy = false;
bool any_host_cert_mapping = false;
/* /*
* Signal the main thread that the application should shut down. * Signal the main thread that the application should shut down.
@ -135,89 +129,6 @@ void SignalShutdown()
PR_Unlock(shutdown_lock); PR_Unlock(shutdown_lock);
} }
bool ReadConnectRequest(server_info_t* server_info,
char* bufferhead, char* buffertail, PRInt32* result, string* certificate)
{
if (buffertail - bufferhead < 4)
return false;
if (strncmp(buffertail-4, "\r\n\r\n", 4))
return false;
*result = 400;
char* token;
token = strtok(bufferhead, " ");
if (!token)
return true;
if (strcmp(token, "CONNECT"))
return true;
token = strtok(NULL, " ");
void* c = PL_HashTableLookup(server_info->host_cert_table, token);
if (c)
*certificate = (char*)c;
token = strtok(NULL, "/");
if (strcmp(token, "HTTP"))
return true;
*result = 200;
return true;
}
bool ConfigureSSLServerSocket(PRFileDesc* socket, server_info_t* si, string &certificate)
{
const char* certnick = certificate.empty() ?
si->cert_nickname.c_str() : certificate.c_str();
AutoCert cert(PK11_FindCertFromNickname(
certnick, NULL));
if (!cert) {
fprintf(stderr, "Failed to find cert %s\n", si->cert_nickname.c_str());
return false;
}
AutoKey privKey(PK11_FindKeyByAnyCert(cert, NULL));
if (!privKey) {
fprintf(stderr, "Failed to find private key\n");
return false;
}
PRFileDesc* ssl_socket = SSL_ImportFD(NULL, socket);
if (!ssl_socket) {
fprintf(stderr, "Error importing SSL socket\n");
return false;
}
SSLKEAType certKEA = NSS_FindCertKEAType(cert);
if (SSL_ConfigSecureServer(ssl_socket, cert, privKey, certKEA)
!= SECSuccess) {
fprintf(stderr, "Error configuring SSL server socket\n");
return false;
}
SSL_OptionSet(ssl_socket, SSL_SECURITY, PR_TRUE);
SSL_OptionSet(ssl_socket, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
SSL_OptionSet(ssl_socket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
SSL_ResetHandshake(ssl_socket, PR_TRUE);
return true;
}
bool ConnectSocket(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
{
PRStatus stat = PR_Connect(fd, addr, timeout);
if (stat != PR_SUCCESS)
return false;
PRSocketOptionData option;
option.option = PR_SockOpt_Nonblocking;
option.value.non_blocking = PR_TRUE;
PR_SetSocketOption(fd, &option);
return true;
}
/* /*
* Handle an incoming client connection. The server thread has already * Handle an incoming client connection. The server thread has already
* accepted the connection, so we just need to connect to the remote * accepted the connection, so we just need to connect to the remote
@ -234,194 +145,43 @@ void PR_CALLBACK HandleConnection(void* data)
AutoFD other_sock(PR_NewTCPSocket()); AutoFD other_sock(PR_NewTCPSocket());
bool client_done = false; bool client_done = false;
bool client_error = false; bool client_error = false;
bool connect_accepted = !do_http_proxy; PRUint8 buf[BUF_SIZE];
bool ssl_updated = !do_http_proxy;
string certificateToUse;
if (other_sock) if (other_sock &&
{ PR_Connect(other_sock, &ci->server_info->remote_addr, connect_timeout)
PRInt32 numberOfSockets = 1; == PR_SUCCESS) {
PRInt32 bytes = PR_Recv(ci->client_sock, buf, BUF_SIZE, 0, short_timeout);
struct relayBuffer if (bytes > 0 &&
{ PR_Send(other_sock, buf, bytes, 0, short_timeout) > 0) {
char *buffer, *bufferhead, *buffertail, *bufferend; bytes = PR_Recv(other_sock, buf, BUF_SIZE, 0, short_timeout);
relayBuffer() while (bytes > 0) {
{ if (PR_Send(ci->client_sock, buf, bytes, 0, short_timeout) == -1) {
bufferhead = buffertail = buffer = new char[BUF_SIZE];
bufferend = buffer + BUF_SIZE;
}
~relayBuffer()
{
delete [] buffer;
}
bool empty()
{
return bufferhead == buffertail;
}
PRInt32 free()
{
return bufferend - buffertail;
}
PRInt32 present()
{
return buffertail - bufferhead;
}
void compact()
{
if (buffertail == bufferhead)
buffertail = bufferhead = buffer;
}
} buffers[2];
if (!do_http_proxy)
{
if (!ConfigureSSLServerSocket(ci->client_sock, ci->server_info, certificateToUse))
client_error = true;
else if (!ConnectSocket(other_sock, &remote_addr, connect_timeout))
client_error = true;
else
numberOfSockets = 2;
}
PRPollDesc sockets[2] =
{
{ci->client_sock, PR_POLL_READ, 0},
{other_sock, PR_POLL_READ, 0}
};
while (!((client_error||client_done) && buffers[0].empty() && buffers[1].empty()))
{
sockets[0].in_flags |= PR_POLL_EXCEPT;
sockets[1].in_flags |= PR_POLL_EXCEPT;
PRInt32 pollStatus = PR_Poll(sockets, numberOfSockets, PR_MillisecondsToInterval(1000));
if (pollStatus < 0)
{
client_error = true;
break;
}
if (pollStatus == 0)
// timeout
continue;
for (PRInt32 s = 0; s < numberOfSockets; ++s)
{
PRInt32 s2 = s == 1 ? 0 : 1;
PRInt16 out_flags = sockets[s].out_flags;
PRInt16 &in_flags = sockets[s].in_flags;
PRInt16 &in_flags2 = sockets[s2].in_flags;
sockets[s].out_flags = 0;
if (out_flags & PR_POLL_EXCEPT)
{
client_error = true; client_error = true;
continue; break;
} // PR_POLL_EXCEPT handling }
if (!client_done) {
if (out_flags & PR_POLL_READ && buffers[s].free()) bytes = PR_Recv(ci->client_sock, buf, BUF_SIZE, 0, short_timeout);
{ if (bytes > 0) {
PRInt32 bytesRead = PR_Recv(sockets[s].fd, buffers[s].buffertail, if (PR_Send(other_sock, buf, bytes, 0, short_timeout) == -1)
buffers[s].free(), 0, PR_INTERVAL_NO_TIMEOUT);
if (bytesRead == 0)
{
client_done = true;
in_flags &= ~PR_POLL_READ;
}
else if (bytesRead < 0)
{
if (PR_GetError() != PR_WOULD_BLOCK_ERROR)
client_error = true;
}
else
{
buffers[s].buffertail += bytesRead;
// We have to accept and handle the initial CONNECT request here
PRInt32 response;
if (!connect_accepted && ReadConnectRequest(ci->server_info, buffers[s].bufferhead, buffers[s].buffertail,
&response, &certificateToUse))
{
// Clean the request as it would be read
buffers[s].bufferhead = buffers[s].buffertail = buffers[s].buffer;
// Store response to the oposite buffer
if (response != 200)
{
client_done = true;
sprintf(buffers[s2].buffer, "HTTP/1.1 %d ERROR\r\nConnection: close\r\n\r\n", response);
buffers[s2].buffertail = buffers[s2].buffer + strlen(buffers[s2].buffer);
break;
}
strcpy(buffers[s2].buffer, "HTTP/1.1 200 Connected\r\nConnection: keep-alive\r\n\r\n");
buffers[s2].buffertail = buffers[s2].buffer + strlen(buffers[s2].buffer);
if (!ConnectSocket(other_sock, &remote_addr, connect_timeout))
{
client_error = true;
break;
}
// Send the response to the client socket
in_flags |= PR_POLL_WRITE;
connect_accepted = true;
break; break;
} // end of CONNECT handling
if (!buffers[s].free()) // Do not poll for read when the buffer is full
in_flags &= ~PR_POLL_READ;
if (ssl_updated)
in_flags2 |= PR_POLL_WRITE;
} }
} // PR_POLL_READ handling else if (bytes == 0) {
client_done = true;
if (out_flags & PR_POLL_WRITE)
{
PRInt32 bytesWrite = PR_Send(sockets[s].fd, buffers[s2].bufferhead,
buffers[s2].present(), 0, PR_INTERVAL_NO_TIMEOUT);
if (bytesWrite < 0)
{
if (PR_GetError() != PR_WOULD_BLOCK_ERROR)
client_error = true;
} }
else else {// error
{ client_error = true;
buffers[s2].bufferhead += bytesWrite; break;
if (buffers[s2].present())
in_flags |= PR_POLL_WRITE;
else
{
if (!ssl_updated)
{
// Proxy response has just been writen, update to ssl
ssl_updated = true;
if (!ConfigureSSLServerSocket(ci->client_sock, ci->server_info, certificateToUse))
{
client_error = true;
break;
}
numberOfSockets = 2;
} // sslUpdate
in_flags &= ~PR_POLL_WRITE;
in_flags2 |= PR_POLL_READ;
buffers[s2].compact();
}
} }
} // PR_POLL_WRITE handling }
} // for... bytes = PR_Recv(other_sock, buf, BUF_SIZE, 0, short_timeout);
} // while, poll }
}
else if (bytes == -1) {
client_error = true;
}
} }
else
client_error = true;
if (!client_error) if (!client_error)
PR_Shutdown(ci->client_sock, PR_SHUTDOWN_SEND); PR_Shutdown(ci->client_sock, PR_SHUTDOWN_BOTH);
PR_Close(ci->client_sock); PR_Close(ci->client_sock);
delete ci; delete ci;
@ -438,6 +198,21 @@ void PR_CALLBACK StartServer(void* data)
server_info_t* si = static_cast<server_info_t*>(data); server_info_t* si = static_cast<server_info_t*>(data);
//TODO: select ciphers? //TODO: select ciphers?
AutoCert cert(PK11_FindCertFromNickname(si->cert_nickname.c_str(),
NULL));
if (!cert) {
fprintf(stderr, "Failed to find cert %s\n", si->cert_nickname.c_str());
SignalShutdown();
return;
}
AutoKey privKey(PK11_FindKeyByAnyCert(cert, NULL));
if (!privKey) {
fprintf(stderr, "Failed to find private key\n");
SignalShutdown();
return;
}
AutoFD listen_socket(PR_NewTCPSocket()); AutoFD listen_socket(PR_NewTCPSocket());
if (!listen_socket) { if (!listen_socket) {
fprintf(stderr, "failed to create socket\n"); fprintf(stderr, "failed to create socket\n");
@ -459,6 +234,21 @@ void PR_CALLBACK StartServer(void* data)
return; return;
} }
PRFileDesc* ssl_socket = SSL_ImportFD(NULL, listen_socket);
if (!ssl_socket) {
fprintf(stderr, "Error importing SSL socket\n");
SignalShutdown();
return;
}
listen_socket.reset(ssl_socket);
if (SSL_ConfigSecureServer(listen_socket, cert, privKey, kt_rsa)
!= SECSuccess) {
fprintf(stderr, "Error configuring SSL listen socket\n");
SignalShutdown();
return;
}
printf("Server listening on port %d with cert %s\n", si->listen_port, printf("Server listening on port %d with cert %s\n", si->listen_port,
si->cert_nickname.c_str()); si->cert_nickname.c_str());
@ -468,12 +258,6 @@ void PR_CALLBACK StartServer(void* data)
// block waiting for connections // block waiting for connections
ci->client_sock = PR_Accept(listen_socket, &ci->client_addr, ci->client_sock = PR_Accept(listen_socket, &ci->client_addr,
PR_INTERVAL_NO_TIMEOUT); PR_INTERVAL_NO_TIMEOUT);
PRSocketOptionData option;
option.option = PR_SockOpt_Nonblocking;
option.value.non_blocking = PR_TRUE;
PR_SetSocketOption(ci->client_sock, &option);
if (ci->client_sock) if (ci->client_sock)
// Not actually using this PRJob*... // Not actually using this PRJob*...
//PRJob* job = //PRJob* job =
@ -492,196 +276,47 @@ char* password_func(PK11SlotInfo* slot, PRBool retry, void* arg)
return ""; return "";
} }
server_info_t* findServerInfo(int portnumber)
{
for (vector<server_info_t>::iterator it = servers.begin();
it != servers.end(); it++)
{
if (it->listen_port == portnumber)
return &(*it);
}
return NULL;
}
int processConfigLine(char* configLine)
{
if (*configLine == 0 || *configLine == '#')
return 0;
char* keyword = strtok(configLine, ":");
// Configure usage of http/ssl tunneling proxy behavior
if (!strcmp(keyword, "httpproxy"))
{
char* value = strtok(NULL, ":");
if (!strcmp(value, "1"))
do_http_proxy = true;
return 0;
}
// Configure the forward address of the target server
if (!strcmp(keyword, "forward"))
{
char* ipstring = strtok(NULL, ":");
if (PR_StringToNetAddr(ipstring, &remote_addr) != PR_SUCCESS) {
fprintf(stderr, "Invalid remote IP address: %s\n", ipstring);
return 1;
}
char* portstring = strtok(NULL, ":");
int port = atoi(portstring);
if (port <= 0) {
fprintf(stderr, "Invalid remote port: %s\n", portstring);
return 1;
}
remote_addr.inet.port = PR_htons(port);
return 0;
}
// Configure all listen sockets and port+certificate bindings
if (!strcmp(keyword, "listen"))
{
char* hostname = strtok(NULL, ":");
char* hostportstring = NULL;
if (strcmp(hostname, "*"))
{
any_host_cert_mapping = true;
hostportstring = strtok(NULL, ":");
}
char* portstring = strtok(NULL, ":");
char* certnick = strtok(NULL, ":");
int port = atoi(portstring);
if (port <= 0) {
fprintf(stderr, "Invalid port specified: %s\n", portstring);
return 1;
}
if (server_info_t* existingServer = findServerInfo(port))
{
char *certnick_copy = new char[strlen(certnick)+1];
char *hostname_copy = new char[strlen(hostname)+strlen(hostportstring)+2];
strcpy(hostname_copy, hostname);
strcat(hostname_copy, ":");
strcat(hostname_copy, hostportstring);
strcpy(certnick_copy, certnick);
PL_HashTableAdd(existingServer->host_cert_table, hostname_copy, certnick_copy);
}
else
{
server_info_t server;
server.cert_nickname = certnick;
server.listen_port = port;
server.host_cert_table = PL_NewHashTable(0, PL_HashString, PL_CompareStrings, PL_CompareStrings, NULL, NULL);
if (!server.host_cert_table)
{
fprintf(stderr, "Internal, could not create hash table\n");
return 1;
}
servers.push_back(server);
}
return 0;
}
// Configure the NSS certificate database directory
if (!strcmp(keyword, "certdbdir"))
{
nssconfigdir = strtok(NULL, "\n");
return 0;
}
printf("Error: keyword \"%s\" unexpected\n", keyword);
return 1;
}
int parseConfigFile(const char* filePath)
{
FILE* f = fopen(filePath, "r");
if (!f)
return 1;
char buffer[1024], *b = buffer;
while (!feof(f))
{
char c;
fscanf(f, "%c", &c);
switch (c)
{
case '\n':
*b++ = 0;
if (processConfigLine(buffer))
return 1;
b = buffer;
case '\r':
continue;
default:
*b++ = c;
}
}
fclose(f);
// Check mandatory items
if (nssconfigdir.empty())
{
printf("Error: missing path to NSS certification database\n,use certdbdir:<path> in the config file\n");
return 1;
}
if (any_host_cert_mapping && !do_http_proxy)
{
printf("Warning: any host-specific certificate configurations are ignored, add httpproxy:1 to allow them\n");
}
return 0;
}
PRIntn PR_CALLBACK freeHashItems(PLHashEntry *he, PRIntn i, void *arg)
{
delete [] (char*)he->key;
delete [] (char*)he->value;
return HT_ENUMERATE_REMOVE;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
char* configFilePath; if (argc < 6) {
if (argc == 1) fprintf(stderr, "Error: not enough arguments\n"
configFilePath = "ssltunnel.cfg"; "Usage: ssltunnel <NSS db path> <remote ip> <remote port> (<certname> <port>)+\n"
else " Provide SSL encrypted tunnels to <remote ip>:<remote port>\n"
configFilePath = argv[1]; " from each port specified in a <certname>,<port> pair.\n"
" <certname> must be the nickname of a server certificate\n"
if (parseConfigFile(configFilePath)) { " installed in the NSS db pointed to by the <NSS db path>.\n");
fprintf(stderr, "Error: config file \"%s\" missing or formating incorrect\n"
"Specify path to the config file as parameter to ssltunnel or \n"
"create ssltunnel.cfg in the working directory.\n\n"
"Example format of the config file:\n\n"
" # Enable http/ssl tunneling proxy-like behavior.\n"
" # If not specified ssltunnel simply does direct forward.\n"
" httpproxy:1\n\n"
" # Specify path to the certification database used.\n"
" certdbdir:/path/to/certdb\n\n"
" # Forward/proxy all requests in raw to 127.0.0.1:8888.\n"
" forward:127.0.0.1:8888\n\n"
" # Accept connections on port 4443 or 5678 resp. and authenticate\n"
" # to any host ('*') using the 'server cert' or 'server cert 2' resp.\n"
" listen:*:4443:server cert\n"
" listen:*:5678:server cert 2\n\n"
" # Accept connections on port 4443 and authenticate using\n"
" # 'a different cert' when target host is 'my.host.name:443'.\n"
" # This works only in httpproxy mode and has higher priority\n"
" # then the previews option.\n"
" listen:my.host.name:443:4443:a different cert\n",
configFilePath);
return 1; return 1;
} }
PRNetAddr remote_addr;
if (PR_StringToNetAddr(argv[2], &remote_addr) != PR_SUCCESS) {
fprintf(stderr, "Invalid remote IP address: %s\n", argv[2]);
return 1;
}
int port = atoi(argv[3]);
if (port <= 0) {
fprintf(stderr, "Invalid remote port: %s\n", argv[2]);
return 1;
}
remote_addr.inet.port = PR_htons(port);
// get our list of cert:port from the remaining args
vector<server_info_t> servers;
for (int i=4; i<argc; i++) {
server_info_t server;
memcpy(&server.remote_addr, &remote_addr, sizeof(PRNetAddr));
server.cert_nickname = argv[i++];
port = atoi(argv[i]);
if (port <= 0) {
fprintf(stderr, "Invalid port specified: %s\n", argv[i]);
return 1;
}
server.listen_port = port;
servers.push_back(server);
}
// create a thread pool to handle connections // create a thread pool to handle connections
threads = PR_CreateThreadPool(std::max<PRInt32>(INITIAL_THREADS, threads = PR_CreateThreadPool(std::max<PRInt32>(INITIAL_THREADS,
servers.size()*2), servers.size()*2),
@ -710,7 +345,9 @@ int main(int argc, char** argv)
PK11_SetPasswordFunc(password_func); PK11_SetPasswordFunc(password_func);
// Initialize NSS // Initialize NSS
if (NSS_Init(nssconfigdir.c_str()) != SECSuccess) { char* configdir = argv[1];
if (NSS_Init(configdir) != SECSuccess) {
PRInt32 errorlen = PR_GetErrorTextLength(); PRInt32 errorlen = PR_GetErrorTextLength();
char* err = new char[errorlen+1]; char* err = new char[errorlen+1];
PR_GetErrorText(err); PR_GetErrorText(err);
@ -761,14 +398,6 @@ int main(int argc, char** argv)
if (NSS_Shutdown() == SECFailure) { if (NSS_Shutdown() == SECFailure) {
fprintf(stderr, "Leaked NSS objects!\n"); fprintf(stderr, "Leaked NSS objects!\n");
} }
for (vector<server_info_t>::iterator it = servers.begin();
it != servers.end(); it++)
{
PL_HashTableEnumerateEntries(it->host_cert_table, freeHashItems, NULL);
PL_HashTableDestroy(it->host_cert_table);
}
PR_Cleanup(); PR_Cleanup();
return 0; return 0;
} }

Просмотреть файл

@ -245,8 +245,6 @@ NO_PKG_FILES += \
res/throbber \ res/throbber \
shlibsign* \ shlibsign* \
ssltunnel* \ ssltunnel* \
certutil* \
pk12util* \
winEmbed.exe \ winEmbed.exe \
os2Embed.exe \ os2Embed.exe \
chrome/chrome.rdf \ chrome/chrome.rdf \