246 lines
11 KiB
Diff
246 lines
11 KiB
Diff
Index: pywbem-20131121/cim_http.py
|
|
===================================================================
|
|
--- pywbem-20131121.orig/cim_http.py
|
|
+++ pywbem-20131121/cim_http.py
|
|
@@ -28,6 +28,7 @@ being transferred is XML. It is up to t
|
|
data and interpret the result.
|
|
'''
|
|
|
|
+from M2Crypto import SSL, Err
|
|
import sys, string, re, os, socket, getpass
|
|
from stat import S_ISSOCK
|
|
import cim_obj
|
|
@@ -74,8 +75,26 @@ def parse_url(url):
|
|
|
|
return host, port, ssl
|
|
|
|
+def get_default_ca_certs():
|
|
+ """
|
|
+ Try to find out system path with ca certificates. This path is cached and
|
|
+ returned. If no path is found out, None is returned.
|
|
+ """
|
|
+ if not hasattr(get_default_ca_certs, '_path'):
|
|
+ for path in (
|
|
+ '/etc/pki/tls/certs',
|
|
+ '/etc/ssl/certs',
|
|
+ '/etc/ssl/certificates'):
|
|
+ if os.path.exists(path):
|
|
+ get_default_ca_certs._path = path
|
|
+ break
|
|
+ else:
|
|
+ get_default_ca_certs._path = None
|
|
+ return get_default_ca_certs._path
|
|
+
|
|
def wbem_request(url, data, creds, headers = [], debug = 0, x509 = None,
|
|
- verify_callback = None):
|
|
+ verify_callback = None, ca_certs = None,
|
|
+ no_verification = False):
|
|
"""Send XML data over HTTP to the specified url. Return the
|
|
response in XML. Uses Python's build-in httplib. x509 may be a
|
|
dictionary containing the location of the SSL certificate and key
|
|
@@ -105,10 +124,35 @@ def wbem_request(url, data, creds, heade
|
|
|
|
class HTTPSConnection(HTTPBaseConnection, httplib.HTTPSConnection):
|
|
def __init__(self, host, port=None, key_file=None, cert_file=None,
|
|
- strict=None):
|
|
+ strict=None, ca_certs=None, verify_callback=None):
|
|
httplib.HTTPSConnection.__init__(self, host, port, key_file,
|
|
cert_file, strict)
|
|
-
|
|
+ self.ca_certs = ca_certs
|
|
+ self.verify_callback = verify_callback
|
|
+
|
|
+ def connect(self):
|
|
+ "Connect to a host on a given (SSL) port."
|
|
+ sock = socket.create_connection((self.host, self.port),
|
|
+ self.timeout, self.source_address)
|
|
+ if self._tunnel_host:
|
|
+ self.sock = sock
|
|
+ self._tunnel()
|
|
+ ctx = SSL.Context('sslv3')
|
|
+ if self.cert_file:
|
|
+ ctx.load_cert(self.cert_file, keyfile=self.key_file)
|
|
+ if self.ca_certs:
|
|
+ ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert,
|
|
+ depth=9, callback=verify_callback)
|
|
+ if os.path.isdir(self.ca_certs):
|
|
+ ctx.load_verify_locations(capath=self.ca_certs)
|
|
+ else:
|
|
+ ctx.load_verify_locations(cafile=self.ca_certs)
|
|
+ try:
|
|
+ self.sock = SSL.Connection(ctx)
|
|
+ self.sock.connect((self.host, self.port))
|
|
+ except (Err.SSLError, SSL.SSLError, SSL.SSLTimeoutError), arg:
|
|
+ raise Error("SSL error: %s" % arg)
|
|
+
|
|
class FileHTTPConnection(HTTPBaseConnection, httplib.HTTPConnection):
|
|
def __init__(self, uds_path):
|
|
httplib.HTTPConnection.__init__(self, 'localhost')
|
|
@@ -117,53 +161,14 @@ def wbem_request(url, data, creds, heade
|
|
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
self.sock.connect(self.uds_path)
|
|
|
|
- host, port, ssl = parse_url(url)
|
|
+ host, port, use_ssl = parse_url(url)
|
|
|
|
key_file = None
|
|
cert_file = None
|
|
|
|
- if ssl:
|
|
-
|
|
- if x509 is not None:
|
|
- cert_file = x509.get('cert_file')
|
|
- key_file = x509.get('key_file')
|
|
-
|
|
- if verify_callback is not None:
|
|
- addr_ind = 0
|
|
- # Temporary exception store
|
|
- addr_exc = None
|
|
- # Get a list of arguments for socket().
|
|
- addr_list = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
|
|
- for addr_ind in xrange(len(addr_list)):
|
|
- family, socktype, proto, canonname, sockaddr = addr_list[addr_ind]
|
|
- try:
|
|
- from OpenSSL import SSL
|
|
- ctx = SSL.Context(SSL.SSLv3_METHOD)
|
|
- ctx.set_verify(SSL.VERIFY_PEER, verify_callback)
|
|
- ctx.set_default_verify_paths()
|
|
- # Add the key and certificate to the session
|
|
- if cert_file is not None and key_file is not None:
|
|
- ctx.use_certificate_file(cert_file)
|
|
- ctx.use_privatekey_file(key_file)
|
|
- s = SSL.Connection(ctx, socket.socket(family, socktype, proto))
|
|
- s.connect((host, port))
|
|
- s.do_handshake()
|
|
- s.shutdown()
|
|
- s.close()
|
|
- addr_exc = None
|
|
- break
|
|
- except (socket.gaierror, socket.error), arg:
|
|
- # Could not perform connect() call, store the exception object for
|
|
- # later use.
|
|
- addr_exc = arg
|
|
- continue
|
|
- except socket.sslerror, arg:
|
|
- raise Error("SSL error: %s" % (arg,))
|
|
-
|
|
- # Did we try all the addresses from getaddrinfo() and no successful
|
|
- # connection performed?
|
|
- if addr_exc:
|
|
- raise Error("Socket error: %s" % (addr_exc),)
|
|
+ if use_ssl and x509 is not None:
|
|
+ cert_file = x509.get('cert_file')
|
|
+ key_file = x509.get('key_file')
|
|
|
|
numTries = 0
|
|
localAuthHeader = None
|
|
@@ -171,10 +176,19 @@ def wbem_request(url, data, creds, heade
|
|
|
|
data = '<?xml version="1.0" encoding="utf-8" ?>\n' + data
|
|
|
|
+ if not no_verification and ca_certs is None:
|
|
+ ca_certs = get_default_ca_certs()
|
|
+ elif no_verification:
|
|
+ ca_certs = None
|
|
+
|
|
local = False
|
|
- if ssl:
|
|
- h = HTTPSConnection(host, port = port, key_file = key_file,
|
|
- cert_file = cert_file)
|
|
+ if use_ssl:
|
|
+ h = HTTPSConnection(host,
|
|
+ port = port,
|
|
+ key_file = key_file,
|
|
+ cert_file = cert_file,
|
|
+ ca_certs = ca_certs,
|
|
+ verify_callback = verify_callback)
|
|
else:
|
|
if url.startswith('http'):
|
|
h = HTTPConnection(host, port = port)
|
|
Index: pywbem-20131121/cim_operations.py
|
|
===================================================================
|
|
--- pywbem-20131121.orig/cim_operations.py
|
|
+++ pywbem-20131121/cim_operations.py
|
|
@@ -78,12 +78,12 @@ class WBEMConnection(object):
|
|
the request before it is sent, and the reply before it is
|
|
unpacked.
|
|
|
|
- verify_callback is used to verify the server certificate.
|
|
- It is passed to OpenSSL.SSL.set_verify, and is called during the SSL
|
|
- handshake. verify_callback should take five arguments: A Connection
|
|
- object, an X509 object, and three integer variables, which are in turn
|
|
- potential error number, error depth and return code. verify_callback
|
|
- should return True if verification passes and False otherwise.
|
|
+ verify_callback is used to verify the server certificate. It is passed to
|
|
+ M2Crypto.SSL.Context.set_verify, and is called during the SSL handshake.
|
|
+ verify_callback should take five arguments: An SSL Context object, an X509
|
|
+ object, and three integer variables, which are in turn potential error
|
|
+ number, error depth and return code. verify_callback should return True if
|
|
+ verification passes and False otherwise.
|
|
|
|
The value of the x509 argument is used only when the url contains
|
|
'https'. x509 must be a dictionary containing the keys 'cert_file'
|
|
@@ -91,14 +91,27 @@ class WBEMConnection(object):
|
|
filename of an certificate and the value of 'key_file' must consist
|
|
of a filename containing the private key belonging to the public key
|
|
that is part of the certificate in cert_file.
|
|
+
|
|
+ ca_certs specifies where CA certificates for verification purposes are
|
|
+ located. These are trusted certificates. Note that the certificates have to
|
|
+ be in PEM format. Either it is a directory prepared using the c_rehash tool
|
|
+ included with OpenSSL or an pemfile. If None, default system path will be
|
|
+ used.
|
|
+
|
|
+ no_verification allows to disable peer's verification. This is insecure and
|
|
+ should be avoided. If True, peer's certificate is not verified and ca_certs
|
|
+ argument is ignored.
|
|
"""
|
|
|
|
def __init__(self, url, creds = None, default_namespace = DEFAULT_NAMESPACE,
|
|
- x509 = None, verify_callback = None):
|
|
+ x509 = None, verify_callback = None, ca_certs = None,
|
|
+ no_verification = False):
|
|
self.url = url
|
|
self.creds = creds
|
|
self.x509 = x509
|
|
self.verify_callback = verify_callback
|
|
+ self.ca_certs = ca_certs
|
|
+ self.no_verification = no_verification
|
|
self.last_request = self.last_reply = ''
|
|
self.default_namespace = default_namespace
|
|
self.debug = False
|
|
@@ -164,7 +177,9 @@ class WBEMConnection(object):
|
|
resp_xml = cim_http.wbem_request(self.url, req_xml.toxml(),
|
|
self.creds, headers,
|
|
x509 = self.x509,
|
|
- verify_callback = self.verify_callback)
|
|
+ verify_callback = self.verify_callback,
|
|
+ ca_certs = self.ca_certs,
|
|
+ no_verification = self.no_verification)
|
|
except cim_http.AuthError:
|
|
raise
|
|
except cim_http.Error, arg:
|
|
@@ -321,7 +336,9 @@ class WBEMConnection(object):
|
|
resp_xml = cim_http.wbem_request(self.url, req_xml.toxml(),
|
|
self.creds, headers,
|
|
x509 = self.x509,
|
|
- verify_callback = self.verify_callback)
|
|
+ verify_callback = self.verify_callback,
|
|
+ ca_certs = self.ca_certs,
|
|
+ no_verification = self.no_verification)
|
|
except cim_http.Error, arg:
|
|
# Convert cim_http exceptions to CIMError exceptions
|
|
raise CIMError(0, str(arg))
|
|
Index: pywbem-20131121/setup.py
|
|
===================================================================
|
|
--- pywbem-20131121.orig/setup.py
|
|
+++ pywbem-20131121/setup.py
|
|
@@ -37,6 +37,7 @@ args = {'name': 'pywbem',
|
|
'version': '0.7.0',
|
|
'license': 'LGPLv2',
|
|
'packages': ['pywbem'],
|
|
+ 'install_requires': ['M2Crypto'],
|
|
# Make packages in root dir appear in pywbem module
|
|
'package_dir': {'pywbem': ''},
|
|
# Make extensions in root dir appear in pywbem module
|