summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimeon Simeonov2015-04-15 13:40:37 +0200
committerSimeon Simeonov2015-04-15 13:40:37 +0200
commit65b5e0fdb857febed888eff7674d80925515c7d5 (patch)
tree7eb8b1b051cc5f683c823166c3197dc34d6d5730
parent0998ece142aed11c75a4a2d4212d8149805fd3d4 (diff)
Start developing beinc_poller.py v2.0
-rwxr-xr-xbeinc_generic_client.py2
-rwxr-xr-xbeinc_poller_xmlrpc.py248
2 files changed, 249 insertions, 1 deletions
diff --git a/beinc_generic_client.py b/beinc_generic_client.py
index a397a0b..2efd7df 100755
--- a/beinc_generic_client.py
+++ b/beinc_generic_client.py
@@ -30,7 +30,7 @@ import xmlrpclib
30 30
31 31
32__author__ = 'Simeon Simeonov' 32__author__ = 'Simeon Simeonov'
33__version__ = '1.0' 33__version__ = '2.0'
34__license__ = 'GPL3' 34__license__ = 'GPL3'
35 35
36 36
diff --git a/beinc_poller_xmlrpc.py b/beinc_poller_xmlrpc.py
new file mode 100755
index 0000000..2efd7df
--- /dev/null
+++ b/beinc_poller_xmlrpc.py
@@ -0,0 +1,248 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Blackmore's Enhanced IRC-Notification Collection (BEINC) v2.0
5# Copyright (C) 2013-2015 Simeon Simeonov
6
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21import argparse
22import errno
23import getpass
24import httplib # for Python < 2.7.9
25import os
26import socket # for Python < 2.7.9
27import ssl
28import sys
29import xmlrpclib
30
31
32__author__ = 'Simeon Simeonov'
33__version__ = '2.0'
34__license__ = 'GPL3'
35
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
46class BEINCCustomHTTPSConnection(httplib.HTTPConnection):
47 """
48 This class allows communication via SSL.
49
50 It is a reimplementation of httplib.HTTPSConnection and
51 allows the server certificate to be validated against CA
52 This functionality lacks in Python < 2.7.9
53 """
54 default_port = httplib.HTTPS_PORT
55
56 def __init__(self, host, port=None, key_file=None, cert_file=None,
57 strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
58 source_address=None, custom_ssl_options={}):
59 httplib.HTTPConnection.__init__(self, host, port, strict, timeout,
60 source_address)
61 self.key_file = key_file
62 self.cert_file = cert_file
63 self.custom_ssl_options = custom_ssl_options
64
65 def connect(self):
66 "Connect to a host on a given (SSL) port."
67 sock = socket.create_connection((self.host, self.port),
68 self.timeout, self.source_address)
69 if self._tunnel_host:
70 self.sock = sock
71 self._tunnel()
72 self.sock = ssl.wrap_socket(sock,
73 self.key_file,
74 self.cert_file,
75 **self.custom_ssl_options)
76
77
78class BEINCCustomSafeTransport(xmlrpclib.Transport):
79
80 def __init__(self, use_datetime=0, custom_ssl_options={}):
81 xmlrpclib.Transport.__init__(self, use_datetime=use_datetime)
82 self.custom_ssl_options = custom_ssl_options
83
84 def make_connection(self, host):
85 if self._connection and host == self._connection[0]:
86 return self._connection[1]
87 try:
88 HTTPS = BEINCCustomHTTPSConnection
89 except AttributeError:
90 raise NotImplementedError(
91 "your version of httplib doesn't support HTTPS"
92 )
93 else:
94 chost, self._extra_headers, x509 = self.get_host_info(host)
95 self._connection = host, HTTPS(
96 chost,
97 None,
98 custom_ssl_options=self.custom_ssl_options,
99 **(x509 or {}))
100 return self._connection[1]
101
102
103def action_execute(args):
104 """
105 """
106 try:
107 ssl_version = BEINC_SSL_METHODS.get(args.ssl_version,
108 ssl.PROTOCOL_SSLv23)
109 if sys.hexversion >= 0x20709f0:
110 # Python >= 2.7.9
111 context = ssl.SSLContext(ssl_version)
112 context.verify_mode = ssl.CERT_REQUIRED
113 if args.no_cert_validate:
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)
120 transport = xmlrpclib.SafeTransport(context=context)
121 else:
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
131 transport = BEINCCustomSafeTransport(
132 custom_ssl_options=ssl_options)
133 server = xmlrpclib.ServerProxy(args.url,
134 transport=transport)
135 if args.pull:
136 print(server.pull(args.rname, args.password))
137 else:
138 print(server.push(args.rname,
139 args.password,
140 args.title,
141 args.message))
142 except xmlrpclib.Fault as fault:
143 sys.stderr.write(
144 'BEINC server answered with errorCode={0}: {1}\n'.format(
145 fault.faultCode,
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)
150 except Exception as e:
151 sys.stderr.write('BEINC generic client error: {0}\n'.format(e))
152 sys.exit(errno.EPERM)
153
154
155def main():
156 parser = argparse.ArgumentParser(
157 description='The following options are available')
158 parser.add_argument('url',
159 metavar='URL',
160 type=str,
161 help='Destination URL')
162 parser.add_argument('-c', '--cert-file',
163 metavar='FILE',
164 type=str,
165 dest='cert',
166 default='',
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)')
174 parser.add_argument('-m', '--message',
175 metavar='MESSAGE',
176 type=str,
177 dest='message',
178 default='BEINC message',
179 help='BEINC message')
180 parser.add_argument('-n', '--resource-name',
181 metavar='NAME',
182 type=str,
183 dest='rname',
184 required=True,
185 help='The name of the BEINC-resource on '
186 'the remote server')
187 parser.add_argument('-p', '--password',
188 metavar='PASSWORD',
189 type=str,
190 dest='password',
191 default='',
192 help='Password')
193 if sys.hexversion >= 0x20709f0:
194 parser.add_argument('-s', '--ssl-version',
195 metavar='VERSION',
196 type=str,
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')
209 parser.add_argument('-t', '--title',
210 metavar='TITLE',
211 type=str,
212 dest='title',
213 default='BEINC title',
214 help='BEINC title')
215 parser.add_argument('-v', '--version',
216 action='version',
217 version='%(prog)s {0}'.format(__version__),
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)')
236 args = parser.parse_args()
237 if not args.password:
238 try:
239 args.password = getpass.getpass()
240 except Exception as e:
241 sys.stderr.write('Prompt terminated\n')
242 sys.exit(errno.EACCES)
243 action_execute(args)
244 sys.exit(0)
245
246
247if __name__ == '__main__':
248 main()