Blame SOURCES/bz1072564-1-add_ssl_secure_and_ssl_insecure.patch

3340af
From 809b909651118c06d2ab48d7911bbee2e512e478 Mon Sep 17 00:00:00 2001
3340af
From: Marek 'marx' Grac <mgrac@redhat.com>
3340af
Date: Mon, 1 Sep 2014 15:05:20 +0200
3340af
Subject: [PATCH 1/2] fencing: Add new options --ssl-secure and --ssl-insecure
3340af
3340af
These new options extends current --ssl (same as --ssl-secure). Until now certificate of the fence device
3340af
was not validated what can possibly lead to attack on infrastructe. With this patch, user can decide
3340af
if certificate should (--ssl-secure) or should not (--ssl-insecure) be verified.
3340af
3340af
The default option is to validate certificate.
3340af
3340af
Resolves: rhbz#1072564
3340af
---
3340af
 fence/agents/cisco_ucs/fence_cisco_ucs.py     |  9 ++++++--
3340af
 fence/agents/lib/fencing.py.py                | 28 ++++++++++++++++++++---
3340af
 fence/agents/rhevm/fence_rhevm.py             |  9 ++++++--
3340af
 fence/agents/vmware_soap/fence_vmware_soap.py | 33 +++++++++++++++++++++++----
3340af
 4 files changed, 68 insertions(+), 11 deletions(-)
3340af
3340af
diff --git a/fence/agents/cisco_ucs/fence_cisco_ucs.py b/fence/agents/cisco_ucs/fence_cisco_ucs.py
3340af
index f72e696..888d689 100644
3340af
--- a/fence/agents/cisco_ucs/fence_cisco_ucs.py
3340af
+++ b/fence/agents/cisco_ucs/fence_cisco_ucs.py
3340af
@@ -90,8 +90,13 @@ def send_command(opt, command, timeout):
3340af
 	conn.setopt(pycurl.POSTFIELDS, command)
3340af
 	conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
3340af
 	conn.setopt(pycurl.TIMEOUT, timeout)
3340af
-	conn.setopt(pycurl.SSL_VERIFYPEER, 0)
3340af
-	conn.setopt(pycurl.SSL_VERIFYHOST, 0)
3340af
+	if opt.has_key("--ssl") or opt.has_key("--ssl-secure"):
3340af
+		conn.setopt(pycurl.SSL_VERIFYPEER, 1)
3340af
+		conn.setopt(pycurl.SSL_VERIFYHOST, 2)
3340af
+
3340af
+	if opt.has_key("--ssl-insecure"):
3340af
+		conn.setopt(pycurl.SSL_VERIFYPEER, 0)
3340af
+		conn.setopt(pycurl.SSL_VERIFYHOST, 0)
3340af
 	conn.perform()
3340af
 	result = web_buffer.getvalue()
3340af
 
3340af
diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py
3340af
index d1d5aae..557358a 100644
3340af
--- a/fence/agents/lib/fencing.py.py
3340af
+++ b/fence/agents/lib/fencing.py.py
3340af
@@ -179,6 +179,21 @@ all_opt = {
3340af
 		"required" : "0",
3340af
 		"shortdesc" : "SSL connection",
3340af
 		"order" : 1},
3340af
+	"ssl_insecure" : {
3340af
+		"getopt" : "9",
3340af
+		"longopt" : "ssl-insecure",
3340af
+		"help" : "--ssl-insecure                 Use ssl connection without verifying certificate",
3340af
+		"required" : "0",
3340af
+		"shortdesc" : "SSL connection without verifying fence device's certificate",
3340af
+		"order" : 1},
3340af
+	"ssl_secure" : {
3340af
+		"getopt" : "9",
3340af
+		"longopt" : "ssl-secure",
3340af
+		"help" : "--ssl-secure                   Use ssl connection with verifying certificate",
3340af
+		"required" : "0",
3340af
+		"shortdesc" : "SSL connection with verifying fence device's certificate",
3340af
+		"order" : 1},
3340af
+
3340af
 	"notls" : {
3340af
 		"getopt" : "t",
3340af
 		"longopt" : "notls",
3340af
@@ -385,6 +400,7 @@ DEPENDENCY_OPT = {
3340af
 		"secure" : ["identity_file", "ssh_options"],
3340af
 		"ipaddr" : ["ipport", "inet4_only", "inet6_only"],
3340af
 		"port" : ["separator"],
3340af
+		"ssl" : ["ssl_secure", "ssl_insecure"],
3340af
 		"community" : ["snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", \
3340af
 			"snmp_priv_passwd", "snmp_priv_passwd_script"]
3340af
 	}
3340af
@@ -662,7 +678,7 @@ def check_input(device_opt, opt):
3340af
 		elif options.has_key("--ssh") or (all_opt["secure"].has_key("default") and all_opt["secure"]["default"] == '1'):
3340af
 			all_opt["ipport"]["default"] = 22
3340af
 			all_opt["ipport"]["help"] = "-u, --ipport=[port]            TCP/UDP port to use (default 22)"
3340af
-		elif options.has_key("--ssl") or (all_opt["ssl"].has_key("default") and all_opt["ssl"]["default"] == '1'):
3340af
+		elif options.has_key("--ssl") or options.has_key("--ssl-secure") or options.has_key("--ssl-insecure") or (all_opt["ssl"].has_key("default") and all_opt["ssl"]["default"] == '1'):
3340af
 			all_opt["ipport"]["default"] = 443
3340af
 			all_opt["ipport"]["help"] = "-u, --ipport=[port]            TCP/UDP port to use (default 443)"
3340af
 		elif device_opt.count("web"):
3340af
@@ -972,11 +988,17 @@ def fence_login(options, re_login_string=r"(login\s*: )|(Login Name:  )|(usernam
3340af
 
3340af
 		if options.has_key("--ssl"):
3340af
 			gnutls_opts = ""
3340af
+			ssl_opts = ""
3340af
+
3340af
 			if options.has_key("--notls"):
3340af
 				gnutls_opts = "--priority \"NORMAL:-VERS-TLS1.2:-VERS-TLS1.1:-VERS-TLS1.0:+VERS-SSL3.0\""
3340af
 
3340af
-			command = '%s %s --insecure --crlf -p %s %s' % \
3340af
-					(SSL_PATH, gnutls_opts, options["--ipport"], options["--ip"])
3340af
+			# --ssl is same as the --ssl-secure
3340af
+			if options.has_key("--ssl-insecure"):
3340af
+				ssl_opts = "--insecure"
3340af
+
3340af
+			command = '%s %s %s --insecure --crlf -p %s %s' % \
3340af
+					(SSL_PATH, gnutls_opts, ssl_opts, options["--ipport"], options["--ip"])
3340af
 			try:
3340af
 				conn = fspawn(options, command)
3340af
 			except pexpect.ExceptionPexpect, ex:
3340af
diff --git a/fence/agents/rhevm/fence_rhevm.py b/fence/agents/rhevm/fence_rhevm.py
3340af
index a0d8d59..444fb56 100644
3340af
--- a/fence/agents/rhevm/fence_rhevm.py
3340af
+++ b/fence/agents/rhevm/fence_rhevm.py
3340af
@@ -91,8 +91,13 @@ def send_command(opt, command, method="GET"):
3340af
 	conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
3340af
 	conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"])
3340af
 	conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
3340af
-	conn.setopt(pycurl.SSL_VERIFYPEER, 0)
3340af
-	conn.setopt(pycurl.SSL_VERIFYHOST, 0)
3340af
+	if opt.has_key("--ssl") or opt.has_key("--ssl-secure"):
3340af
+		conn.setopt(pycurl.SSL_VERIFYPEER, 1)
3340af
+		conn.setopt(pycurl.SSL_VERIFYHOST, 2)
3340af
+
3340af
+	if opt.has_key("--ssl-insecure"):
3340af
+		conn.setopt(pycurl.SSL_VERIFYPEER, 0)
3340af
+		conn.setopt(pycurl.SSL_VERIFYHOST, 0)
3340af
 
3340af
 	if method == "POST":
3340af
 		conn.setopt(pycurl.POSTFIELDS, "<action />")
3340af
diff --git a/fence/agents/vmware_soap/fence_vmware_soap.py b/fence/agents/vmware_soap/fence_vmware_soap.py
3340af
index 53fd9ea..3217c6b 100644
3340af
--- a/fence/agents/vmware_soap/fence_vmware_soap.py
3340af
+++ b/fence/agents/vmware_soap/fence_vmware_soap.py
3340af
@@ -2,12 +2,14 @@
3340af
 
3340af
 import sys
3340af
 import shutil, tempfile, suds
3340af
-import logging
3340af
+import logging, requests
3340af
 import atexit
3340af
 sys.path.append("@FENCEAGENTSLIBDIR@")
3340af
 
3340af
 from suds.client import Client
3340af
 from suds.sudsobject import Property
3340af
+from suds.transport.http import HttpAuthenticated
3340af
+from suds.transport import Reply, TransportError
3340af
 from fencing import *
3340af
 from fencing import fail, EC_STATUS, EC_LOGIN_DENIED, EC_INVALID_PRIVILEGES, EC_WAITING_ON, EC_WAITING_OFF
3340af
 from fencing import run_delay
3340af
@@ -18,12 +20,31 @@ REDHAT_COPYRIGHT=""
3340af
 BUILD_DATE="April, 2011"
3340af
 #END_VERSION_GENERATION
3340af
 
3340af
+class RequestsTransport(HttpAuthenticated):
3340af
+	def __init__(self, **kwargs):
3340af
+		self.cert = kwargs.pop('cert', None)
3340af
+		self.verify = kwargs.pop('verify', True)
3340af
+		self.session = requests.Session()
3340af
+		# super won't work because not using new style class
3340af
+		HttpAuthenticated.__init__(self, **kwargs)
3340af
+
3340af
+	def send(self, request):
3340af
+		self.addcredentials(request)
3340af
+		resp = self.session.post(request.url, data = request.message, headers = request.headers, cert = self.cert, verify = self.verify)
3340af
+		result = Reply(resp.status_code, resp.headers, resp.content)
3340af
+		return result
3340af
+
3340af
 def soap_login(options):
3340af
 	run_delay(options)
3340af
 
3340af
-	if options.has_key("--ssl"):
3340af
+	if options.has_key("--ssl") or options.has_key("--ssl-secure") or options.has_key("--ssl-insecure"):
3340af
+		if options.has_key("--ssl-insecure"):
3340af
+			verify = False
3340af
+		else:
3340af
+			verify = True
3340af
 		url = "https://"
3340af
 	else:
3340af
+		verify = False
3340af
 		url = "http://"
3340af
 
3340af
 	url += options["--ip"] + ":" + str(options["--ipport"]) + "/sdk"
3340af
@@ -33,8 +54,8 @@ def soap_login(options):
3340af
 	atexit.register(remove_tmp_dir, tmp_dir)
3340af
 
3340af
 	try:
3340af
-		conn = Client(url + "/vimService.wsdl")
3340af
-		conn.set_options(location=url)
3340af
+		headers = {"Content-Type" : "text/xml;charset=UTF-8", "SOAPAction" : ""}
3340af
+		conn = Client(url + "/vimService.wsdl", location = url, transport = RequestsTransport(verify = verify), headers = headers)
3340af
 
3340af
 		mo_ServiceInstance = Property('ServiceInstance')
3340af
 		mo_ServiceInstance._type = 'ServiceInstance'
3340af
@@ -43,6 +64,8 @@ def soap_login(options):
3340af
 		mo_SessionManager._type = 'SessionManager'
3340af
 
3340af
 		conn.service.Login(mo_SessionManager, options["--username"], options["--password"])
3340af
+	except requests.exceptions.SSLError, ex:
3340af
+		fail_usage("Server side certificate verification failed")
3340af
 	except Exception:
3340af
 		fail(EC_LOGIN_DENIED)
3340af
 
3340af
@@ -205,6 +228,8 @@ Alternatively you can always use UUID to access virtual machine."
3340af
 
3340af
 	logging.basicConfig(level=logging.INFO)
3340af
 	logging.getLogger('suds.client').setLevel(logging.CRITICAL)
3340af
+	logging.getLogger("requests").setLevel(logging.CRITICAL)
3340af
+	logging.getLogger("urllib3").setLevel(logging.CRITICAL)
3340af
 
3340af
 	##
3340af
 	## Operate the fencing device
3340af
-- 
3340af
1.9.3
3340af