diff options
author | Narayan Desai <desai@mcs.anl.gov> | 2009-05-19 01:40:51 +0000 |
---|---|---|
committer | Narayan Desai <desai@mcs.anl.gov> | 2009-05-19 01:40:51 +0000 |
commit | 260f66263dbb3104eabb930f86bf1fff02389509 (patch) | |
tree | 08bfa8a8fd95f65ae4c5c7424988c4ba0bd34918 /src/lib | |
parent | 229c86e87a277fac5756dd9c33267b4780113198 (diff) | |
download | bcfg2-260f66263dbb3104eabb930f86bf1fff02389509.tar.gz bcfg2-260f66263dbb3104eabb930f86bf1fff02389509.tar.bz2 bcfg2-260f66263dbb3104eabb930f86bf1fff02389509.zip |
SSL: Implememt client-side server cN verification
git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@5244 ce84e21b-d406-0410-9b95-82705330c041
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Options.py | 6 | ||||
-rw-r--r-- | src/lib/Proxy.py | 27 |
2 files changed, 28 insertions, 5 deletions
diff --git a/src/lib/Options.py b/src/lib/Options.py index add106869..a2d9d46ca 100644 --- a/src/lib/Options.py +++ b/src/lib/Options.py @@ -217,6 +217,11 @@ CLIENT_CERT = Option('Path to SSL certificate', default=None, cmd="--ssl-cert", CLIENT_CA = Option('Path to SSL CA Cert', default=None, cmd="--ca-cert", cf=('communication', 'ca'), odesc='<ca cert>', long_arg=True) +CLIENT_SCNS = Option('list of server commonNames', default=None, cmd="--ssl-cns", + cf=('communication', 'serverCommonNames'), + odesc='<commonName1:commonName2>', cook=list_split, + long_arg=True) + SERVER_PASSWORD = Option('Communication Password', cmd='-x', odesc='<password>', cf=('communication', 'password'), default=False) INSTALL_PREFIX = Option('Installation location', cf=('server', 'prefix'), @@ -276,6 +281,7 @@ LOGGING_FILE_PATH = Option('Set path of file log', default=None, CLIENT_SERVICE_MODE = Option('Set client service mode', default='default', cmd='-s', odesc='<default|disabled|build>') + class OptionParser(OptionSet): ''' OptionParser bootstraps option parsing, diff --git a/src/lib/Proxy.py b/src/lib/Proxy.py index 2dd1b0065..3595b1099 100644 --- a/src/lib/Proxy.py +++ b/src/lib/Proxy.py @@ -27,6 +27,10 @@ has_py26 = map(int, version) >= [2, 6] __all__ = ["ComponentProxy", "RetryMethod", "SSLHTTPConnection", "XMLRPCTransport"] +class CertificateError(Exception): + def __init__(self, commonName): + self.commonName = commonName + class RetryMethod(_Method): """Method with error handling and retries built in""" log = logging.getLogger('xmlrpc') @@ -45,6 +49,10 @@ class RetryMethod(_Method): if retry == 3: self.log.error("Server failure: %s" % err) raise xmlrpclib.Fault(20, err) + except CertificateError, ce: + self.log.error("Got unallowed commonName %s from server" \ + % ce.commonName) + break except: self.log.error("Unknown failure", exc_info=1) break @@ -56,7 +64,7 @@ xmlrpclib._Method = RetryMethod class SSLHTTPConnection(httplib.HTTPConnection): def __init__(self, host, port=None, strict=None, timeout=90, key=None, - cert=None, ca=None): + cert=None, ca=None, scns=None): if not has_py26: httplib.HTTPConnection.__init__(self, host, port, strict) else: @@ -64,6 +72,7 @@ class SSLHTTPConnection(httplib.HTTPConnection): self.key = key self.cert = cert self.ca = ca + self.scns = scns if self.ca: self.ca_mode = ssl.CERT_REQUIRED else: @@ -77,20 +86,27 @@ class SSLHTTPConnection(httplib.HTTPConnection): ca_certs=self.ca, suppress_ragged_eofs=True, keyfile=self.key, certfile=self.cert) self.sock.connect((self.host, self.port)) + pc = self.sock.getpeercert() + if pc and self.scns: + scn = [x[0][1] for x in pc['subject'] if x[0][0] == 'commonName'][0] + if scn not in self.scns: + raise CertificateError, scn self.sock.closeSocket = True class XMLRPCTransport(xmlrpclib.Transport): - def __init__(self, key=None, cert=None, ca=None, use_datetime=0): + def __init__(self, key=None, cert=None, ca=None, scns=None, use_datetime=0): if hasattr(xmlrpclib.Transport, '__init__'): xmlrpclib.Transport.__init__(self, use_datetime) self.key = key self.cert = cert self.ca = ca + self.scns = scns def make_connection(self, host): host = self.get_host_info(host)[0] - http = SSLHTTPConnection(host, key=self.key, cert=self.cert, ca=self.ca) + http = SSLHTTPConnection(host, key=self.key, cert=self.cert, ca=self.ca, + scns=self.scns) https = httplib.HTTP() https._setup(http) return https @@ -134,7 +150,8 @@ class XMLRPCTransport(xmlrpclib.Transport): return u.close() -def ComponentProxy (url, user=None, password=None, key=None, cert=None, ca=None): +def ComponentProxy (url, user=None, password=None, key=None, cert=None, ca=None, + allowedServerCNs=None): """Constructs proxies to components. @@ -149,6 +166,6 @@ def ComponentProxy (url, user=None, password=None, key=None, cert=None, ca=None) newurl = "%s://%s:%s@%s" % (method, user, password, path) else: newurl = url - ssl_trans = XMLRPCTransport(key, cert, ca) + ssl_trans = XMLRPCTransport(key, cert, ca, allowedServerCNs) return xmlrpclib.ServerProxy(newurl, allow_none=True, transport=ssl_trans) |