@ -14,8 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import urllib2 as u2
import urllib . request as u2
if hasattr ( u2 , " ssl " ) :
u2 . ssl . _create_default_https_context = u2 . ssl . _create_unverified_context
import os
@ -25,23 +24,18 @@ import ssl
import OpenSSL
import hashlib
import M2Crypto
import calculate . contrib
from calculate . core . datavars import DataVarsCore
from calculate . lib . datavars import DataVars
import calculate . contrib
from suds . client import Client
from cert_verify import verify , get_CRL
import http lib
from . cert_verify import verify , get_CRL
import http . client as http lib
from suds . transport . http import HttpTransport
try :
from pyopenssl_wrapper import PyOpenSSLSocket
except ImportError :
PYOPENSSL_AVAILABLE = False
else :
PYOPENSSL_AVAILABLE = True
from . pyopenssl_wrapper import PyOpenSSLSocket
from suds . transport import Transport
from suds . properties import Unskin
from cookielib import CookieJar , DefaultCookiePolicy
from http . cookiejar import CookieJar , DefaultCookiePolicy
from logging import getLogger
from calculate . console . datavars import DataVarsConsole
from calculate . lib . cl_lang import setLocalTranslate
@ -80,94 +74,58 @@ class SUDSHTTPRedirectHandler(u2.HTTPRedirectHandler):
else :
raise u2 . HTTPError ( req . get_full_url ( ) , code , msg , headers , fp )
class MyHTTPResponse ( httplib . HTTPResponse ) :
def __init__ ( self , sock , debuglevel = 0 , strict = 0 , method = None ) :
httplib . HTTPResponse . __init__ ( self , sock , debuglevel , strict , method )
class CheckingHTTPSConnection ( httplib . HTTPSConnection ) :
""" based on httplib.HTTPSConnection code - extended to support
server certificate verification and client certificate authorization """
response_class = MyHTTPResponse
FORCE_SSL_VERSION = None
SERVER_CERT_CHECK = True # might be turned off when a workaround is needed
def __init__ ( self , host , ca_certs = None , cert_verifier = None ,
keyobj = None , certobj = None , * * kw ) :
""" cert_verifier is a function returning either True or False
based on whether the certificate was found to be OK ,
keyobj and certobj represent internal PyOpenSSL structures holding
the key and certificate respectively .
"""
httplib . HTTPSConnection . __init__ ( self , host , * * kw )
self . ca_certs = ca_certs
self . cert_verifier = cert_verifier
self . keyobj = keyobj
self . certobj = certobj
def connect ( self ) :
sock = socket . create_connection ( ( self . host , self . port ) , self . timeout )
if hasattr ( self , ' _tunnel_host ' ) and self . _tunnel_host :
self . sock = sock
self . _tunnel ( )
if self . FORCE_SSL_VERSION :
add = { ' ssl_version ' : self . FORCE_SSL_VERSION }
else :
add = { }
if self . SERVER_CERT_CHECK and self . ca_certs :
add [ ' cert_reqs ' ] = ssl . CERT_REQUIRED
else :
add [ ' cert_reqs ' ] = ssl . CERT_NONE
# try to use PyOpenSSL by default
if PYOPENSSL_AVAILABLE :
wrap_class = PyOpenSSLSocket
add [ ' keyobj ' ] = self . keyobj
add [ ' certobj ' ] = self . certobj
add [ ' keyfile ' ] = self . key_file
add [ ' certfile ' ] = self . cert_file
else :
wrap_class = ssl . SSLSocket
self . sock = wrap_class ( sock , ca_certs = self . ca_certs , * * add )
#if self.cert_verifier and self.SERVER_CERT_CHECK:
# if not self.cert_verifier(self.sock.getpeercert()):
# raise Exception("Server certificate did not pass security check.",
# self.sock.getpeercert())
class CheckingHTTPSHandler ( u2 . HTTPSHandler ) :
def __init__ ( self , ca_certs = None , cert_verifier = None ,
client_certfile = None , client_keyfile = None ,
client_keyobj = None , client_certobj = None ,
* args , * * kw ) :
""" cert_verifier is a function returning either True or False
based on whether the certificate was found to be OK """
u2 . HTTPSHandler . __init__ ( self , * args , * * kw )
self . ca_certs = ca_certs
self . cert_verifier = cert_verifier
self . client_keyfile = client_keyfile # filename
self . client_certfile = client_certfile # filename
self . keyobj = client_keyobj
self . certobj = client_certobj
# FOR DEBUG
# self.set_http_debuglevel(100)
def https_open ( self , req ) :
def open ( * args , * * kw ) :
new_kw = dict ( ca_certs = self . ca_certs ,
cert_verifier = self . cert_verifier ,
cert_file = self . client_certfile ,
key_file = self . client_keyfile ,
keyobj = self . keyobj ,
certobj = self . certobj )
new_kw . update ( kw )
return CheckingHTTPSConnection ( * args , * * new_kw )
return self . do_open ( open , req )
https_request = u2 . AbstractHTTPHandler . do_request_
# class CheckingHTTPSConnection(httplib.HTTPSConnection):
# """based on httplib.HTTPSConnection code - extended to support
# server certificate verification and client certificate authorization"""
# response_class = MyHTTPResponse
# FORCE_SSL_VERSION = None
# SERVER_CERT_CHECK = True # might be turned off when a workaround is needed
# def __init__(self, host, ca_certs=None, cert_verifier=None,
# keyobj=None, certobj=None, **kw):
# """cert_verifier is a function returning either True or False
# based on whether the certificate was found to be OK,
# keyobj and certobj represent internal PyOpenSSL structures holding
# the key and certificate respectively.
# """
# httplib.HTTPSConnection.__init__(self, host, **kw)
# self.ca_certs = ca_certs
# self.cert_verifier = cert_verifier
# self.keyobj = keyobj
# self.certobj = certobj
# def connect(self):
# sock = socket.create_connection((self.host, self.port), self.timeout)
# if hasattr(self, '_tunnel_host') and self._tunnel_host:
# self.sock = sock
# self._tunnel()
# if self.FORCE_SSL_VERSION:
# add = {'ssl_version': self.FORCE_SSL_VERSION}
# else:
# add = {}
# if self.SERVER_CERT_CHECK and self.ca_certs:
# add['cert_reqs'] = ssl.CERT_REQUIRED
# else:
# add['cert_reqs'] = ssl.CERT_NONE
# # try to use PyOpenSSL by default
# if PYOPENSSL_AVAILABLE:
# wrap_class = PyOpenSSLSocket
# add['keyobj'] = self.keyobj
# add['certobj'] = self.certobj
# add['keyfile'] = self.key_file
# add['certfile'] = self.cert_file
# else:
# wrap_class = ssl.SSLSocket
# self.sock = wrap_class(sock, ca_certs=self.ca_certs, **add)
# #if self.cert_verifier and self.SERVER_CERT_CHECK:
# # if not self.cert_verifier(self.sock.getpeercert()):
# # raise Exception("Server certificate did not pass security check.",
# # self.sock.getpeercert())
class Client_suds ( SessionId , Client ) :
@ -187,9 +145,12 @@ class Client_suds(SessionId, Client):
class CheckingClientHTTPSConnection ( CheckingHTTPSConnection ) :
""" based on httplib.HTTPSConnection code - extended to support
server certificate verification and client certificate authorization """
class CheckingClientHTTPSConnection ( httplib . HTTPSConnection ) :
""" based on httplib.HTTPSConnection code """
response_class = httplib . HTTPResponse
FORCE_SSL_VERSION = None
SERVER_CERT_CHECK = True # might be turned off when a workaround is needed
def __init__ ( self , cert_path , host , ca_certs = None , cert_verifier = None ,
keyobj = None , certobj = None , wait_thread = None , * * kw ) :
@ -198,11 +159,12 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
keyobj and certobj represent internal PyOpenSSL structures holding
the key and certificate respectively .
"""
CheckingHTTPSConnection . __init__ ( self , host , ca_certs , cert_verifier ,
keyobj , certobj , * * kw )
# self.ClientObj = ClientObj
self . cert_path = cert_path
httplib . HTTPSConnection . __init__ ( self , host , * * kw )
self . ca_certs = ca_certs
self . cert_verifier = cert_verifier
self . keyobj = keyobj
self . certobj = certobj
self . cert_path = cert_path
self . CRL_PATH = os . path . join ( cert_path , ' ca/crl/ ' )
self . wait_thread = wait_thread
@ -233,7 +195,7 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
if not filename :
return None
except :
print _ ( " Certificate not found on the client`s side " )
print ( _ ( " Certificate not found on the client`s side " ) )
return None
try :
fd = open ( self . trusted_path + filename , ' r ' )
@ -242,7 +204,7 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
if store_cert == server_cert :
return filename
except :
print _ ( " Failed to open the file " ) , self . trusted_path , filename
print ( _ ( " Failed to open the file " ) , self . trusted_path , filename )
return None
def add_all_ca_cert ( self , list_ca_certs ) :
@ -276,8 +238,8 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
md5 = hashlib . md5 ( )
md5 . update ( cert )
md5sum = md5 . hexdigest ( )
print " \n ================================================= "
print " md5sum = " , md5sum
print ( " \n ================================================= " )
print ( " md5sum = " , md5sum )
if not os . path . exists ( root_cert_md5 ) :
fc = open ( root_cert_md5 , " w " )
@ -305,7 +267,7 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
fc . close ( )
if not filename :
print _ ( ' Field " CN " not found in the certificate! ' )
print ( _ ( ' Field " CN " not found in the certificate! ' ) )
return 1
fd = open ( os . path . join ( cl_client_cert_dir , ' ca/ ' , filename ) ,
@ -316,10 +278,10 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
fa = open ( user_root_cert , ' a ' )
fa . write ( cert )
fa . close ( )
print _ ( " filename = " ) , filename
print _ ( " Certificate added " )
print ( _ ( " filename = " ) , filename )
print ( _ ( " Certificate added " ) )
else :
print _ ( " The file containing the CA certificate now exists " )
print ( _ ( " The file containing the CA certificate now exists " ) )
get_CRL ( cl_client_cert_dir )
def add_ca_cert ( self , cert , list_ca_certs ) :
@ -329,55 +291,55 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
client . wsdl . services [ 0 ] . setlocation ( url )
cert = client . service . get_ca ( )
if cert == ' 1 ' :
print _ ( " Invalid server certificate! " )
print ( _ ( " Invalid server certificate! " ) )
raise Exception ( 1 )
if cert == ' 2 ' :
print _ ( " CA certificate not found on the server " )
print ( _ ( " CA certificate not found on the server " ) )
raise Exception ( 1 )
try :
certobj = OpenSSL . crypto . load_certificate (
OpenSSL . SSL . FILETYPE_PEM , cert )
except :
print _ ( " Error. Certificate not added to trusted " )
print ( _ ( " Error. Certificate not added to trusted " ) )
raise Exception ( 1 )
print ' \n ' , _ ( " Fingerprint = %s " ) % certobj . digest ( ' SHA1 ' )
print _ ( " Serial Number = " ) , certobj . get_serial_number ( )
print ( ' \n ' , _ ( " Fingerprint = %s " ) % certobj . digest ( ' SHA1 ' ) )
print ( _ ( " Serial Number = " ) , certobj . get_serial_number ( ) )
Issuer = certobj . get_issuer ( ) . get_components ( )
print ' \n ' , _ ( " Issuer " )
print ( ' \n ' , _ ( " Issuer " ) )
for i in Issuer :
print " %s : %s " % ( i [ 0 ] , i [ 1 ] )
print ( " %s : %s " % ( i [ 0 ] , i [ 1 ] ) )
Subject = certobj . get_subject ( ) . get_components ( )
print ' \n ' , _ ( " Subject " )
print ( ' \n ' , _ ( " Subject " ) )
for subj in Subject :
print " %s : %s " % ( subj [ 0 ] , subj [ 1 ] )
print ( " %s : %s " % ( subj [ 0 ] , subj [ 1 ] ) )
ans = raw_input ( _ ( " Add the CA certificate to trusted? y/[n]: " ) )
if ans . lower ( ) in [ ' y ' , ' yes ' ] :
list_ca_certs . append ( cert )
self . add_all_ca_cert ( list_ca_certs )
else :
print _ ( " Certificate not added to trusted " )
print ( _ ( " Certificate not added to trusted " ) )
# add certificate server in trusted
def add_server_cert ( self , cert ) :
self . wait_thread . stop ( )
print _ ( " Untrusted server certificate! " )
print ( _ ( " Untrusted server certificate! " ) )
certobj = OpenSSL . crypto . load_certificate (
OpenSSL . SSL . FILETYPE_PEM , cert )
print ' \n ' + _ ( " Fingerprint = %s " ) % certobj . digest ( ' SHA1 ' )
print _ ( " Serial Number = " ) , certobj . get_serial_number ( )
print ( ' \n ' + _ ( " Fingerprint = %s " ) % certobj . digest ( ' SHA1 ' ) )
print ( _ ( " Serial Number = " ) , certobj . get_serial_number ( ) )
Issuer = certobj . get_issuer ( ) . get_components ( )
print ' \n ' + _ ( " Issuer " )
print ( ' \n ' + _ ( " Issuer " ) )
for i in Issuer :
print " %s : %s " % ( i [ 0 ] , i [ 1 ] )
print ( " %s : %s " % ( i [ 0 ] , i [ 1 ] ) )
Subject = certobj . get_subject ( ) . get_components ( )
print ' \n ' + _ ( " Subject " )
print ( ' \n ' + _ ( " Subject " ) )
for item in Subject :
print " %s : %s " % ( item [ 0 ] , item [ 1 ] )
print ( " %s : %s " % ( item [ 0 ] , item [ 1 ] ) )
print ' \n ' + _ ( ' Add this server certificate to trusted (s) or ' )
print _ ( ' Try to add the CA and root certificates to trusted (c) or ' )
print ( ' \n ' + _ ( ' Add this server certificate to trusted (s) or ' ) )
print ( _ ( ' Try to add the CA and root certificates to trusted (c) or ' ) )
choice = raw_input ( _ ( " Quit (q)? s/c/[q]: " ) )
if choice . lower ( ) in [ ' s ' , ' c ' ] :
# self.sock = ssl.wrap_socket(sock)
@ -424,10 +386,10 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
try :
os . makedirs ( root_cert_dir )
except OSError :
print _ ( " Failed to create directory %s " ) % root_cert_dir
print ( _ ( " Failed to create directory %s " ) % root_cert_dir )
raise Exception ( 1 )
print ' \n ' + _ ( " Add the CA and root certificates " )
print ( ' \n ' + _ ( " Add the CA and root certificates " ) )
self . list_ca_certs = [ ]
self . add_ca_cert ( cert , self . list_ca_certs )
return 3
@ -456,16 +418,11 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
else :
add = { }
add [ ' cert_reqs ' ] = ssl . CERT_REQUIRED
# try to use PyOpenSSL by default
if PYOPENSSL_AVAILABLE :
wrap_class = PyOpenSSLSocket
add [ ' keyobj ' ] = self . keyobj
add [ ' certobj ' ] = self . certobj
add [ ' keyfile ' ] = self . key_file
add [ ' certfile ' ] = self . cert_file
else :
wrap_class = ssl . SSLSocket
self . sock = wrap_class ( sock , ca_certs = self . ca_certs , * * add )
add [ ' keyobj ' ] = self . keyobj
add [ ' certobj ' ] = self . certobj
add [ ' keyfile ' ] = self . key_file
add [ ' certfile ' ] = self . cert_file
self . sock = PyOpenSSLSocket ( sock , ca_certs = self . ca_certs , * * add )
return 0
except :
return 1
@ -492,17 +449,11 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
else :
add = { }
add [ ' cert_reqs ' ] = ssl . CERT_NONE
# try to use PyOpenSSL by default
if PYOPENSSL_AVAILABLE :
wrap_class = PyOpenSSLSocket
add [ ' keyobj ' ] = self . keyobj
add [ ' certobj ' ] = self . certobj
add [ ' keyfile ' ] = self . key_file
add [ ' certfile ' ] = self . cert_file
else :
wrap_class = ssl . SSLSocket
self . sock = wrap_class ( sock , ca_certs = None , * * add )
add [ ' keyobj ' ] = self . keyobj
add [ ' certobj ' ] = self . certobj
add [ ' keyfile ' ] = self . key_file
add [ ' certfile ' ] = self . cert_file
self . sock = PyOpenSSLSocket ( sock , ca_certs = None , * * add )
return 0
except Exception :
HTTPSClientCertTransport . filename = None
@ -556,7 +507,7 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
elif result_server_con == 3 :
continue
elif result_server_con == 4 :
print _ ( ' This server is not trusted ' )
print ( _ ( ' This server is not trusted ' ) )
self . wait_thread . stop ( )
sys . exit ( 1 )
elif result_root_con == 2 :
@ -566,19 +517,24 @@ class CheckingClientHTTPSConnection(CheckingHTTPSConnection):
break
class CheckingClientHTTPSHandler ( CheckingHTTPSHandler ) :
class CheckingClientHTTPSHandler ( u2 . HTTPSHandler ) :
def __init__ ( self , cert_path , ca_certs = None , cert_verifier = None ,
client_certfile = None , client_keyfile = None ,
client_keyobj = None , client_certobj = None , wait_thread = None ,
client_keyobj = None , client_certobj = None ,
* args , * * kw ) :
""" cert_verifier is a function returning either True or False
based on whether the certificate was found to be OK """
CheckingHTTPSHandler . __init__ ( self , ca_certs , cert_verifier ,
client_keyfile , client_certfile ,
client_keyobj , client_certobj )
# self.ClientObj = ClientObj
u2 . HTTPSHandler . __init__ ( self , * args , * * kw )
self . ca_certs = ca_certs
self . cert_verifier = cert_verifier
self . client_keyfile = client_keyfile # filename
self . client_certfile = client_certfile # filename
self . keyobj = client_keyobj
self . certobj = client_certobj
# FOR DEBUG
# self.set_http_debuglevel(100)
self . cert_path = cert_path
self . wait_thread = wait_thread
def https_open ( self , req ) :
def open ( * args , * * kw ) :
@ -586,12 +542,10 @@ class CheckingClientHTTPSHandler(CheckingHTTPSHandler):
cert_verifier = self . cert_verifier ,
cert_file = self . client_certfile ,
key_file = self . client_keyfile ,
keyobj = self . keyobj , certobj = self . certobj ,
wait_thread= self . wait_thread )
keyobj = self . keyobj ,
certobj= self . certobj )
new_kw . update ( kw )
return CheckingClientHTTPSConnection ( self . cert_path ,
* args , * * new_kw )
return CheckingClientHTTPSConnection ( self . cert_path , * args , * * new_kw )
return self . do_open ( open , req )
https_request = u2 . AbstractHTTPHandler . do_request_
@ -605,60 +559,68 @@ class HTTPSClientCertTransport(HttpTransport):
cookie_callback = None , user_agent_string = None ,
wait_thread = None , * * kwargs ) :
Transport . __init__ ( self )
# self.ClientObj = parent
self . key = key
self . cert = cert
self . cert_path = path_to_cert
if key :
client_certobj = OpenSSL . crypto . load_certificate (
OpenSSL . SSL . FILETYPE_PEM , file ( cert ) . read ( ) )
if password :
client_keyobj = OpenSSL . crypto . load_privatekey (
OpenSSL . SSL . FILETYPE_PEM , file ( key ) . read ( ) , str ( password ) )
else :
bio = M2Crypto . BIO . openfile ( key )
rsa = M2Crypto . m2 . rsa_read_key ( bio . _ptr ( ) , lambda * unused : " " )
if not rsa :
raise OpenSSL . crypto . Error
client_keyobj = OpenSSL . crypto . load_privatekey (
OpenSSL . SSL . FILETYPE_PEM , file ( key ) . read ( ) )
with open ( cert ) as cert_file :
client_certobj = OpenSSL . crypto . load_certificate \
( OpenSSL . SSL . FILETYPE_PEM , cert_file . read ( ) )
if password :
with open ( key ) as key_file :
client_keyobj = OpenSSL . crypto . load_privatekey \
( OpenSSL . SSL . FILETYPE_PEM , key_file . read ( ) ,
password )
else :
import M2Crypto
bio = M2Crypto . BIO . openfile ( key )
rsa = M2Crypto . m2 . rsa_read_key ( bio . _ptr ( ) , lambda * unused : b " " )
if not rsa :
raise OpenSSL . crypto . Error
with open ( key ) as key_file :
client_keyobj = OpenSSL . crypto . load_privatekey ( OpenSSL . SSL . FILETYPE_PEM ,
key_file . read ( ) )
Unskin ( self . options ) . update ( kwargs )
self . cookiejar = CookieJar ( DefaultCookiePolicy ( ) )
self . cookie_callback = cookie_callback
self . user_agent_string = user_agent_string
log . debug ( " Proxy: %s " , self . options . proxy )
#TODO to be removed:
# artifacts from old times:
if ca_certs or ( client_keyfile and client_certfile ) \
or ( client_keyobj and client_certobj ) :
https_handler = CheckingClientHTTPSHandler ( cert_path = path_to_cert ,
ca_certs = ca_certs ,
cert_verifier = cert_verifier ,
client_keyfile = client_keyfile ,
client_certfile = client_certfile ,
client_keyobj = client_keyobj ,
client_certobj = client_certobj )
else :
https_handler = u2 . HTTPSHandler ( )
self . urlopener = u2 . build_opener ( SUDSHTTPRedirectHandler ( ) ,
u2 . HTTPCookieProcessor ( self . cookiejar ) ,
https_handler )
# relic from old times:
# from dslib.network import ProxyManager
# proxy_handler = ProxyManager.HTTPS_PROXY.create_proxy_handler()
# proxy_auth_handler = ProxyManager.HTTPS_PROXY.create_proxy_auth_handler()
# apparently, dslib simply returned None on create_proxy_auth_handler
# if this is ever needed, probably use urllib2.ProxyBasicAuthHandler
proxy_auth_handler = None
# proxy_auth_handler = None
# and create_proxy_handler SHOULD HAVE eval'd to this:
# proxy_handler = urllib2.ProxyHandler({"https" : "https://hostname"})
# but because no hostname was given, it also just returned None
proxy_handler = None
if ( ca_certs or ( client_keyfile and client_certfile )
or ( client_keyobj and client_certobj ) ) :
https_handler = CheckingClientHTTPSHandler (
cert_path = path_to_cert ,
ca_certs = ca_certs ,
cert_verifier = cert_verifier ,
client_keyfile = client_keyfile ,
client_certfile = client_certfile ,
client_keyobj = client_keyobj ,
client_certobj = client_certobj ,
wait_thread = wait_thread )
else :
https_handler = u2 . HTTPSHandler ( )
self . urlopener = u2 . build_opener ( SUDSHTTPRedirectHandler ( ) ,
u2 . HTTPCookieProcessor ( self . cookiejar ) ,
https_handler )
if proxy_handler :
self . urlopener . add_handler ( proxy_handler )
if proxy_auth_handler :
self . urlopener . add_handler ( proxy_auth_handler )
self . urlopener . addheaders = [ ( ' User-agent ' , self . user_agent_string ) ]
# proxy_handler = None
#these two literally do nothing right now
# if proxy_handler:
# self.urlopener.add_handler(proxy_handler)
# if proxy_auth_handler:
# self.urlopener.add_handler(proxy_auth_handler)
self . urlopener . addheaders = [ ( ' User-agent ' , str ( self . user_agent_string ) ) ]