diff options
| author | Simeon Simeonov | 2015-04-14 10:38:43 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2015-04-14 10:38:43 +0200 |
| commit | 4aea82a1aef53c28110cc45c734b835efdc361b3 (patch) | |
| tree | 7f380d3a8982364081f0d32904454a0878f81782 | |
| parent | d606cbfc4932dd67cdb272a32e8103998fd3312a (diff) | |
beinc_config_sample.json beinc_config_sample.json.readme and beinc_server_xmlrpc.py almost complete
| -rw-r--r-- | beinc_config_sample.json | 7 | ||||
| -rw-r--r-- | beinc_config_sample.json.readme | 26 | ||||
| -rwxr-xr-x | beinc_server_xmlrpc.py | 75 |
3 files changed, 76 insertions, 32 deletions
diff --git a/beinc_config_sample.json b/beinc_config_sample.json index f9423a2..c61a033 100644 --- a/beinc_config_sample.json +++ b/beinc_config_sample.json | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | { | 1 | { |
| 2 | "server": { | 2 | "server": { |
| 3 | "general": { | 3 | "general": { |
| 4 | "ssl_module": "pyopenssl", | ||
| 5 | "ssl_private_key": "key.pem", | 4 | "ssl_private_key": "key.pem", |
| 6 | "ssl_certificate": "cert.crt", | 5 | "ssl_certificate": "cert.crt", |
| 6 | "ssl_acceptable_ciphers": "auto", | ||
| 7 | "ssl_method": "auto", | ||
| 7 | "daemonize": 1 | 8 | "daemonize": 1 |
| 8 | }, | 9 | }, |
| 9 | "instances": [ | 10 | "instances": [ |
| @@ -27,7 +28,7 @@ | |||
| 27 | "targets": [ | 28 | "targets": [ |
| 28 | { | 29 | { |
| 29 | "name": "weechat_main", | 30 | "name": "weechat_main", |
| 30 | "target_url": "https://10.0.0.2:9898/push/secondtest", | 31 | "target_url": "https://10.0.0.2:9898", |
| 31 | "target_password": "changeme", | 32 | "target_password": "changeme", |
| 32 | "target_cert_file": "", | 33 | "target_cert_file": "", |
| 33 | "target_timestamp_format": "%H:%M:%S", | 34 | "target_timestamp_format": "%H:%M:%S", |
| @@ -52,5 +53,5 @@ | |||
| 52 | } | 53 | } |
| 53 | ] | 54 | ] |
| 54 | }, | 55 | }, |
| 55 | "config_version": 1 | 56 | "config_version": 2 |
| 56 | } | 57 | } |
diff --git a/beinc_config_sample.json.readme b/beinc_config_sample.json.readme index 12a1b2d..3ac85a9 100644 --- a/beinc_config_sample.json.readme +++ b/beinc_config_sample.json.readme | |||
| @@ -16,17 +16,27 @@ documentation to better illustrate the comments. | |||
| 16 | # It is only used by beinc_server.py and ignored by all other | 16 | # It is only used by beinc_server.py and ignored by all other |
| 17 | # components | 17 | # components |
| 18 | 18 | ||
| 19 | "general": { # Applies to the whole server (cherrypy) For more info: | 19 | "general": { # Applies to the whole server |
| 20 | # http://docs.cherrypy.org/en/latest/refman/_cpserver.html | ||
| 21 | |||
| 22 | # The name of a registered SSL adaptation module | ||
| 23 | "ssl_module": "pyopenssl", | ||
| 24 | 20 | ||
| 25 | # The filename of the private key to use with SSL. | 21 | # The filename of the private key to use with SSL. |
| 26 | "ssl_private_key": "/home/user/keys/key.pem", # default: None | 22 | "ssl_private_key": "/home/user/keys/key.pem", # default: None |
| 27 | 23 | ||
| 28 | # The filename of the SSL certificate to use | 24 | # The filename of the SSL certificate to use |
| 29 | "ssl_certificate": "/home/user/certs/cert.crt" # default: None | 25 | "ssl_certificate": "/home/user/certs/cert.crt", # default: None |
| 26 | |||
| 27 | # A list of allowed ciphers in the format of 'openssl ciphers' | ||
| 28 | # "auto" - use the Twisted / OpenSSL defaults | ||
| 29 | "ssl_acceptable_ciphers": "auto", # default: "auto" | ||
| 30 | |||
| 31 | # Encryption method for the BEINC server | ||
| 32 | # Possible values: | ||
| 33 | # "auto" - Let Twisted decide (use the newest possible method) | ||
| 34 | # "SSLv3" - SSLv3 (weak) | ||
| 35 | # "TLSv1" - TLSv1.0 | ||
| 36 | # "TLSv1_1" - TLSv1.1 | ||
| 37 | # "TLSv1_2" - TLSv1.2 (most secure, but requires OpenSSL >= 1.0.1e) | ||
| 38 | "ssl_method": "auto", # default: "auto" | ||
| 39 | |||
| 30 | }, | 40 | }, |
| 31 | 41 | ||
| 32 | # A list of instances. Check README for general information about them! | 42 | # A list of instances. Check README for general information about them! |
| @@ -185,10 +195,10 @@ documentation to better illustrate the comments. | |||
| 185 | ] | 195 | ] |
| 186 | }, | 196 | }, |
| 187 | # The version of this config file | 197 | # The version of this config file |
| 188 | # Default: 1 (you should really never leave it undefined) | 198 | # Default: 2 (you should really never leave it undefined) |
| 189 | # Used by beinc_server and beinc_weechat to check whether | 199 | # Used by beinc_server and beinc_weechat to check whether |
| 190 | # the config (.json) file is outdated. | 200 | # the config (.json) file is outdated. |
| 191 | # Every future version of BEINC will be shipped with | 201 | # Every future version of BEINC will be shipped with |
| 192 | # beinc_config_sample.json and beinc_config_sample.json.readme | 202 | # beinc_config_sample.json and beinc_config_sample.json.readme |
| 193 | "config_version": 1 | 203 | "config_version": 2 |
| 194 | } | 204 | } |
diff --git a/beinc_server_xmlrpc.py b/beinc_server_xmlrpc.py index a9d0fa5..39cf422 100755 --- a/beinc_server_xmlrpc.py +++ b/beinc_server_xmlrpc.py | |||
| @@ -27,6 +27,8 @@ import sys | |||
| 27 | 27 | ||
| 28 | import OpenSSL | 28 | import OpenSSL |
| 29 | 29 | ||
| 30 | from functools import wraps | ||
| 31 | |||
| 30 | from twisted.web import xmlrpc, server | 32 | from twisted.web import xmlrpc, server |
| 31 | from twisted.internet import protocol, reactor, ssl | 33 | from twisted.internet import protocol, reactor, ssl |
| 32 | from twisted.python.filepath import FilePath | 34 | from twisted.python.filepath import FilePath |
| @@ -49,7 +51,7 @@ except ImportError as e: | |||
| 49 | 51 | ||
| 50 | 52 | ||
| 51 | __author__ = 'Simeon Simeonov' | 53 | __author__ = 'Simeon Simeonov' |
| 52 | __version__ = '1.1' | 54 | __version__ = '2.0' |
| 53 | __license__ = 'GPL3' | 55 | __license__ = 'GPL3' |
| 54 | 56 | ||
| 55 | 57 | ||
| @@ -57,6 +59,17 @@ BEINC_OSD_TYPE_NONE = 0 | |||
| 57 | BEINC_OSD_TYPE_PYNOTIFY = 1 | 59 | BEINC_OSD_TYPE_PYNOTIFY = 1 |
| 58 | BEINC_OSD_TYPE_PYOSD = 2 | 60 | BEINC_OSD_TYPE_PYOSD = 2 |
| 59 | 61 | ||
| 62 | BEINC_SSL_METHODS = {'SSLv3': OpenSSL.SSL.SSLv3_METHOD, | ||
| 63 | 'TLSv1': OpenSSL.SSL.TLSv1_METHOD} | ||
| 64 | try: | ||
| 65 | errstr = "Warning: Current Twisted / OpenSSL version doesn't support TLSv1.1" | ||
| 66 | BEINC_SSL_METHODS.update({'TLSv1_1': OpenSSL.SSL.TLSv1_1_METHOD}) | ||
| 67 | errstr = "Warning: Current Twisted / OpenSSL version doesn't support TLSv1.2" | ||
| 68 | BEINC_SSL_METHODS.update({'TLSv1_2': OpenSSL.SSL.TLSv1_2_METHOD}) | ||
| 69 | except: | ||
| 70 | sys.stderr.write(errstr + '\n') | ||
| 71 | |||
| 72 | |||
| 60 | class BEINCInstance(object): | 73 | class BEINCInstance(object): |
| 61 | """ | 74 | """ |
| 62 | Represents a single server-instance | 75 | Represents a single server-instance |
| @@ -201,6 +214,7 @@ def beinc_login_required(method): | |||
| 201 | decorator for checking login credentials | 214 | decorator for checking login credentials |
| 202 | """ | 215 | """ |
| 203 | 216 | ||
| 217 | @wraps(method) | ||
| 204 | def wrapper(self, resource_name, password, *args, **kwargs): | 218 | def wrapper(self, resource_name, password, *args, **kwargs): |
| 205 | try: | 219 | try: |
| 206 | instance = self.instances[resource_name] | 220 | instance = self.instances[resource_name] |
| @@ -268,11 +282,12 @@ class XMLRPCNotifyServer(xmlrpc.XMLRPC): | |||
| 268 | e)) | 282 | e)) |
| 269 | raise xmlrpc.Fault(500, 'Unable to send message') | 283 | raise xmlrpc.Fault(500, 'Unable to send message') |
| 270 | 284 | ||
| 285 | @beinc_login_required | ||
| 271 | def xmlrpc_pull(self, resource_name, password): | 286 | def xmlrpc_pull(self, resource_name, password): |
| 272 | """ | 287 | """ |
| 273 | Return sum of arguments. | 288 | Return sum of arguments. |
| 274 | """ | 289 | """ |
| 275 | instance = self.__instances[args[0]] | 290 | instance = self.__instances[resource_name] |
| 276 | if not instance.queueable: | 291 | if not instance.queueable: |
| 277 | raise xmlrpc.Fault( | 292 | raise xmlrpc.Fault( |
| 278 | 405, | 293 | 405, |
| @@ -323,30 +338,48 @@ def main(): | |||
| 323 | with open(args.config_file, 'r') as fp: | 338 | with open(args.config_file, 'r') as fp: |
| 324 | config_dict = json.load(fp) | 339 | config_dict = json.load(fp) |
| 325 | except Exception as e: | 340 | except Exception as e: |
| 326 | sys.stderr.write('Unable to parse {0}: {1}'.format(args.config_file, | 341 | sys.stderr.write('Unable to parse {0}: {1}\n'.format(args.config_file, |
| 327 | e)) | 342 | e)) |
| 328 | sys.exit(errno.EIO) | 343 | sys.exit(errno.EIO) |
| 329 | ssl_certificate = config_dict['server']['general']['ssl_certificate'] | 344 | try: |
| 330 | ssl_private_key = config_dict['server']['general']['ssl_private_key'] | 345 | if config_dict.get(config_version) != 2: |
| 331 | try: | 346 | sys.stderr.write( |
| 347 | 'Incompatible or missing config-file version for {0}\n'.format( | ||
| 348 | args.config_file)) | ||
| 349 | sys.exit(1) | ||
| 350 | ssl_certificate = config_dict['server']['general'].get( | ||
| 351 | 'ssl_certificate') | ||
| 352 | ssl_private_key = config_dict['server']['general'].get( | ||
| 353 | 'ssl_private_key') | ||
| 354 | ssl_method_str = config_dict['server']['general'].get( | ||
| 355 | 'ssl_method', 'auto') | ||
| 356 | ssl_acceptable_ciphers_str = config_dict['server']['general'].get( | ||
| 357 | 'ssl_acceptable_ciphers', 'auto') | ||
| 332 | beinc_server = XMLRPCNotifyServer(config_dict) | 358 | beinc_server = XMLRPCNotifyServer(config_dict) |
| 333 | cert_path = FilePath( | 359 | if ssl_certificate and ssl_private_key: |
| 334 | config_dict['server']['general']['ssl_certificate']) | 360 | # SSL connection |
| 335 | key_path = FilePath( | 361 | cert_path = FilePath(ssl_certificate) |
| 336 | config_dict['server']['general']['ssl_private_key']) | 362 | key_path = FilePath(ssl_private_key) |
| 337 | private_certificate = ssl.PrivateCertificate.loadPEM( | 363 | private_certificate = ssl.PrivateCertificate.loadPEM( |
| 338 | key_path.getContent() + cert_path.getContent()) | 364 | key_path.getContent() + cert_path.getContent()) |
| 339 | options = private_certificate.options() | 365 | options = private_certificate.options() |
| 340 | options.method = OpenSSL.SSL.TLSv1_2_METHOD | 366 | ssl_method = BEINC_SSL_METHODS.get(ssl_method_str) |
| 341 | # options.acceptableCiphers = | 367 | if ssl_method: |
| 342 | # ssl.AcceptableCiphers.fromOpenSSLCipherString('EXP-RC4-MD5') | 368 | options.method = ssl_method |
| 343 | reactor.listenSSL(args.port, | 369 | if ssl_acceptable_ciphers_str.lower() != 'auto': |
| 344 | server.Site(beinc_server), | 370 | options.acceptableCiphers = ssl.AcceptableCiphers.fromOpenSSLCipherString( |
| 345 | options, | 371 | ssl_acceptable_ciphers_str) |
| 346 | interface=args.hostname) | 372 | reactor.listenSSL(args.port, |
| 373 | server.Site(beinc_server), | ||
| 374 | options, | ||
| 375 | interface=args.hostname) | ||
| 376 | else: | ||
| 377 | reactor.listenTCP(args.port, | ||
| 378 | server.Site(beinc_server), | ||
| 379 | interface=args.hostname) | ||
| 347 | reactor.run() | 380 | reactor.run() |
| 348 | except Exception as e: | 381 | except Exception as e: |
| 349 | sys.stderr.write("WebServer error: {0}".format(e)) | 382 | sys.stderr.write('WebServer error: {0}\n'.format(e)) |
| 350 | sys.exit(1) | 383 | sys.exit(1) |
| 351 | sys.exit(0) | 384 | sys.exit(0) |
| 352 | 385 | ||
