summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimeon Simeonov2015-04-15 11:50:05 +0200
committerSimeon Simeonov2015-04-15 11:50:05 +0200
commit0998ece142aed11c75a4a2d4212d8149805fd3d4 (patch)
treed0f6893dcd17ddf6a3e918777fb65d217b365a99
parenta5a26cba29ba37f3ef7c4f60c6cbf3f663161b27 (diff)
beinc_server_.py and beinc_generic_client.py ready for version 2.0
-rwxr-xr-xbeinc_generic_client.py104
-rwxr-xr-xbeinc_server_.py15
2 files changed, 92 insertions, 27 deletions
diff --git a/beinc_generic_client.py b/beinc_generic_client.py
index da671f2..a397a0b 100755
--- a/beinc_generic_client.py
+++ b/beinc_generic_client.py
@@ -34,6 +34,15 @@ __version__ = '1.0'
34__license__ = 'GPL3' 34__license__ = 'GPL3'
35 35
36 36
37BEINC_SSL_METHODS = {'SSLv3': ssl.PROTOCOL_SSLv3,
38 'TLSv1': ssl.PROTOCOL_TLSv1}
39try:
40 BEINC_SSL_METHODS.update({'TLSv1_1': ssl.PROTOCOL_TLSv1_1})
41 BEINC_SSL_METHODS.update({'TLSv1_2': ssl.PROTOCOL_TLSv1_2})
42except:
43 pass
44
45
37class BEINCCustomHTTPSConnection(httplib.HTTPConnection): 46class BEINCCustomHTTPSConnection(httplib.HTTPConnection):
38 """ 47 """
39 This class allows communication via SSL. 48 This class allows communication via SSL.
@@ -46,12 +55,12 @@ class BEINCCustomHTTPSConnection(httplib.HTTPConnection):
46 55
47 def __init__(self, host, port=None, key_file=None, cert_file=None, 56 def __init__(self, host, port=None, key_file=None, cert_file=None,
48 strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, 57 strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
49 source_address=None, ca_cert=None): 58 source_address=None, custom_ssl_options={}):
50 httplib.HTTPConnection.__init__(self, host, port, strict, timeout, 59 httplib.HTTPConnection.__init__(self, host, port, strict, timeout,
51 source_address) 60 source_address)
52 self.key_file = key_file 61 self.key_file = key_file
53 self.cert_file = cert_file 62 self.cert_file = cert_file
54 self.ca_cert = ca_cert 63 self.custom_ssl_options = custom_ssl_options
55 64
56 def connect(self): 65 def connect(self):
57 "Connect to a host on a given (SSL) port." 66 "Connect to a host on a given (SSL) port."
@@ -63,15 +72,15 @@ class BEINCCustomHTTPSConnection(httplib.HTTPConnection):
63 self.sock = ssl.wrap_socket(sock, 72 self.sock = ssl.wrap_socket(sock,
64 self.key_file, 73 self.key_file,
65 self.cert_file, 74 self.cert_file,
66 cert_reqs=ssl.CERT_REQUIRED, 75 **self.custom_ssl_options)
67 ca_certs=self.ca_cert) 76
68 77
69class BEINCCustomSafeTransport(xmlrpclib.Transport): 78class BEINCCustomSafeTransport(xmlrpclib.Transport):
70 79
71 def __init__(self, use_datetime=0, ca_cert=None): 80 def __init__(self, use_datetime=0, custom_ssl_options={}):
72 xmlrpclib.Transport.__init__(self, use_datetime=use_datetime) 81 xmlrpclib.Transport.__init__(self, use_datetime=use_datetime)
73 self.ca_cert = ca_cert 82 self.custom_ssl_options = custom_ssl_options
74 83
75 def make_connection(self, host): 84 def make_connection(self, host):
76 if self._connection and host == self._connection[0]: 85 if self._connection and host == self._connection[0]:
77 return self._connection[1] 86 return self._connection[1]
@@ -83,10 +92,11 @@ class BEINCCustomSafeTransport(xmlrpclib.Transport):
83 ) 92 )
84 else: 93 else:
85 chost, self._extra_headers, x509 = self.get_host_info(host) 94 chost, self._extra_headers, x509 = self.get_host_info(host)
86 self._connection = host, HTTPS(chost, 95 self._connection = host, HTTPS(
87 None, 96 chost,
88 ca_cert=self.ca_cert, 97 None,
89 **(x509 or {})) 98 custom_ssl_options=self.custom_ssl_options,
99 **(x509 or {}))
90 return self._connection[1] 100 return self._connection[1]
91 101
92 102
@@ -94,17 +104,32 @@ def action_execute(args):
94 """ 104 """
95 """ 105 """
96 try: 106 try:
107 ssl_version = BEINC_SSL_METHODS.get(args.ssl_version,
108 ssl.PROTOCOL_SSLv23)
97 if sys.hexversion >= 0x20709f0: 109 if sys.hexversion >= 0x20709f0:
98 # Python >= 2.7.9 110 # Python >= 2.7.9
99 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) 111 context = ssl.SSLContext(ssl_version)
100 context.verify_mode = ssl.CERT_REQUIRED 112 context.verify_mode = ssl.CERT_REQUIRED
101 context.check_hostname = False 113 if args.no_cert_validate:
102 context.load_verify_locations(os.path.expanduser(args.cert)) 114 context.verify_mode = ssl.CERT_NONE
115 context.check_hostname = bool(not args.disable_hostname_check)
116 if args.cert and not args.no_cert_validate:
117 context.load_verify_locations(os.path.expanduser(args.cert))
118 if args.ciphers:
119 context.set_ciphers(args.ciphers)
103 transport = xmlrpclib.SafeTransport(context=context) 120 transport = xmlrpclib.SafeTransport(context=context)
104 else: 121 else:
105 # Python < 2.7.9 122 # Python < 2.7.9
123 ssl_options = {}
124 ssl_options['ssl_version'] = ssl_version
125 if args.cert and not args.no_cert_validate:
126 ssl_options['ca_certs'] = os.path.expanduser(args.cert)
127 if not args.no_cert_validate:
128 ssl_options['cert_reqs'] = ssl.CERT_REQUIRED
129 if args.ciphers:
130 ssl_options['ciphers'] = args.ciphers
106 transport = BEINCCustomSafeTransport( 131 transport = BEINCCustomSafeTransport(
107 ca_cert=os.path.expanduser(args.cert)) 132 custom_ssl_options=ssl_options)
108 server = xmlrpclib.ServerProxy(args.url, 133 server = xmlrpclib.ServerProxy(args.url,
109 transport=transport) 134 transport=transport)
110 if args.pull: 135 if args.pull:
@@ -119,6 +144,9 @@ def action_execute(args):
119 'BEINC server answered with errorCode={0}: {1}\n'.format( 144 'BEINC server answered with errorCode={0}: {1}\n'.format(
120 fault.faultCode, 145 fault.faultCode,
121 fault.faultString)) 146 fault.faultString))
147 except ssl.SSLError as e:
148 sys.stderr.write('BEINC SSL/TLS error: {0}\n'.format(e))
149 sys.exit(errno.EPERM)
122 except Exception as e: 150 except Exception as e:
123 sys.stderr.write('BEINC generic client error: {0}\n'.format(e)) 151 sys.stderr.write('BEINC generic client error: {0}\n'.format(e))
124 sys.exit(errno.EPERM) 152 sys.exit(errno.EPERM)
@@ -137,6 +165,12 @@ def main():
137 dest='cert', 165 dest='cert',
138 default='', 166 default='',
139 help='BEINC CA-cert to check the server-cert against') 167 help='BEINC CA-cert to check the server-cert against')
168 parser.add_argument('-C', '--ciphers',
169 metavar='CIPHERS',
170 type=str,
171 dest='ciphers',
172 default='',
173 help='Preferred ciphers list (default: auto)')
140 parser.add_argument('-m', '--message', 174 parser.add_argument('-m', '--message',
141 metavar='MESSAGE', 175 metavar='MESSAGE',
142 type=str, 176 type=str,
@@ -156,11 +190,22 @@ def main():
156 dest='password', 190 dest='password',
157 default='', 191 default='',
158 help='Password') 192 help='Password')
159 parser.add_argument('--pull', 193 if sys.hexversion >= 0x20709f0:
160 action='store_true', 194 parser.add_argument('-s', '--ssl-version',
161 dest='pull', 195 metavar='VERSION',
162 default=False, 196 type=str,
163 help='Perform a pull operation (default: push)') 197 dest='ssl_version',
198 default='auto',
199 help='Use SSL version: auto (default), '
200 'SSLv3, TLSv1, TLSv1_1, TLSv1_2')
201 else:
202 parser.add_argument('-s', '--ssl-version',
203 metavar='VERSION',
204 type=str,
205 dest='ssl_version',
206 default='auto',
207 help='Use SSL version: auto (default), '
208 'SSLv3, TLSv1')
164 parser.add_argument('-t', '--title', 209 parser.add_argument('-t', '--title',
165 metavar='TITLE', 210 metavar='TITLE',
166 type=str, 211 type=str,
@@ -171,6 +216,23 @@ def main():
171 action='version', 216 action='version',
172 version='%(prog)s {0}'.format(__version__), 217 version='%(prog)s {0}'.format(__version__),
173 help='display program-version and exit') 218 help='display program-version and exit')
219 if sys.hexversion >= 0x20709f0:
220 parser.add_argument('--disable-hostname-check',
221 action='store_true',
222 dest='disable_hostname_check',
223 default=False,
224 help='Do not check whether server cert '
225 'matches server hostname')
226 parser.add_argument('--no-cert-validate',
227 action='store_true',
228 dest='no_cert_validate',
229 default=False,
230 help='Do not validate server certificate')
231 parser.add_argument('--pull',
232 action='store_true',
233 dest='pull',
234 default=False,
235 help='Perform a pull operation (default: push)')
174 args = parser.parse_args() 236 args = parser.parse_args()
175 if not args.password: 237 if not args.password:
176 try: 238 try:
@@ -181,6 +243,6 @@ def main():
181 action_execute(args) 243 action_execute(args)
182 sys.exit(0) 244 sys.exit(0)
183 245
184 246
185if __name__ == '__main__': 247if __name__ == '__main__':
186 main() 248 main()
diff --git a/beinc_server_.py b/beinc_server_.py
index ec920c2..cf4f7c7 100755
--- a/beinc_server_.py
+++ b/beinc_server_.py
@@ -62,9 +62,11 @@ BEINC_OSD_TYPE_PYOSD = 2
62BEINC_SSL_METHODS = {'SSLv3': OpenSSL.SSL.SSLv3_METHOD, 62BEINC_SSL_METHODS = {'SSLv3': OpenSSL.SSL.SSLv3_METHOD,
63 'TLSv1': OpenSSL.SSL.TLSv1_METHOD} 63 'TLSv1': OpenSSL.SSL.TLSv1_METHOD}
64try: 64try:
65 errstr = "Warning: Current Twisted / OpenSSL version doesn't support TLSv1.1" 65 errstr = ("Warning: Current Twisted / "
66 "OpenSSL version doesn't support TLSv1.1")
66 BEINC_SSL_METHODS.update({'TLSv1_1': OpenSSL.SSL.TLSv1_1_METHOD}) 67 BEINC_SSL_METHODS.update({'TLSv1_1': OpenSSL.SSL.TLSv1_1_METHOD})
67 errstr = "Warning: Current Twisted / OpenSSL version doesn't support TLSv1.2" 68 errstr = ("Warning: Current Twisted / " +
69 "OpenSSL version doesn't support TLSv1.2")
68 BEINC_SSL_METHODS.update({'TLSv1_2': OpenSSL.SSL.TLSv1_2_METHOD}) 70 BEINC_SSL_METHODS.update({'TLSv1_2': OpenSSL.SSL.TLSv1_2_METHOD})
69except: 71except:
70 sys.stderr.write(errstr + '\n') 72 sys.stderr.write(errstr + '\n')
@@ -217,7 +219,7 @@ class BEINCInstance(object):
217 219
218def beinc_login_required(method): 220def beinc_login_required(method):
219 """ 221 """
220 decorator for checking login credentials 222 Decorator for checking login credentials
221 """ 223 """
222 224
223 @wraps(method) 225 @wraps(method)
@@ -339,8 +341,8 @@ def main():
339 action='version', 341 action='version',
340 version='%(prog)s {0}'.format(__version__), 342 version='%(prog)s {0}'.format(__version__),
341 help='Display program-version and exit') 343 help='Display program-version and exit')
342 log.startLogging(sys.stdout)
343 args = parser.parse_args() 344 args = parser.parse_args()
345 log.startLogging(sys.stdout)
344 try: 346 try:
345 with open(args.config_file, 'r') as fp: 347 with open(args.config_file, 'r') as fp:
346 config_dict = json.load(fp) 348 config_dict = json.load(fp)
@@ -374,8 +376,9 @@ def main():
374 if ssl_method: 376 if ssl_method:
375 options.method = ssl_method 377 options.method = ssl_method
376 if ssl_acceptable_ciphers_str.lower() != 'auto': 378 if ssl_acceptable_ciphers_str.lower() != 'auto':
377 options.acceptableCiphers = ssl.AcceptableCiphers.fromOpenSSLCipherString( 379 options.acceptableCiphers = (
378 ssl_acceptable_ciphers_str) 380 ssl.AcceptableCiphers.fromOpenSSLCipherString(
381 ssl_acceptable_ciphers_str))
379 reactor.listenSSL(args.port, 382 reactor.listenSSL(args.port,
380 server.Site(beinc_server), 383 server.Site(beinc_server),
381 options, 384 options,