2 # -*- coding: utf-8 -*-
4 # ------------------------------------------------------------
5 # opensecurity_client_restful_server
7 # the OpenSecurity client RESTful server
9 # Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
11 # Copyright (C) 2013 AIT Austrian Institute of Technology
12 # AIT Austrian Institute of Technology GmbH
13 # Donau-City-Strasse 1 | 1220 Vienna | Austria
14 # http://www.ait.ac.at
16 # This program is free software; you can redistribute it and/or
17 # modify it under the terms of the GNU General Public License
18 # as published by the Free Software Foundation version 2.
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 # Boston, MA 02110-1301, USA.
29 # ------------------------------------------------------------
32 # ------------------------------------------------------------
47 from environment import Environment
50 # ------------------------------------------------------------
57 """All the URLs we know mapping to class handler"""
59 '/credentials', 'os_credentials',
60 '/keyfile', 'os_keyfile',
61 '/notification', 'os_notification',
62 '/password', 'os_password',
67 # ------------------------------------------------------------
73 """OpenSecurity '/credentials' handler.
75 This is called on GET /credentials?text=TEXT.
76 Ideally this should pop up a user dialog to insert his
77 credentials based the given TEXT.
86 if not "text" in args:
87 raise web.badrequest('no text given')
90 remote_ip = web.ctx.environ['REMOTE_ADDR']
92 # create the process which queries the user
93 dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
94 process_command = [sys.executable, dlg_image, 'credentials', args.text]
95 process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
97 # run process result handling in seprate thread (not to block main one)
98 bouncer = UserResultBouncer(process, remote_ip, '/credentials')
101 return 'user queried for credentials'
106 """OpenSecurity '/keyfile' handler.
108 This is called on GET /keyfile?text=TEXT.
109 Ideally this should pop up a user dialog to insert his
110 password along with a keyfile.
119 if not "text" in args:
120 raise web.badrequest('no text given')
123 remote_ip = web.ctx.environ['REMOTE_ADDR']
125 # create the process which queries the user
126 dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
127 process_command = [sys.executable, dlg_image, 'keyfile', args.text]
128 process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
130 # run process result handling in seprate thread (not to block main one)
131 bouncer = UserResultBouncer(process, remote_ip, '/keyfile')
134 return 'user queried for password and keyfile'
137 class os_notification:
139 """OpenSecurity '/notification' handler.
141 This is called on GET /notification?msgtype=TYPE&text=TEXT.
142 This will pop up an OpenSecurity notifcation window
151 if not "msgtype" in args:
152 raise web.badrequest('no msgtype given')
154 if not args.msgtype in ['information', 'warning', 'critical']:
155 raise web.badrequest('Unknown value for msgtype')
158 if not "text" in args:
159 raise web.badrequest('no text given')
161 # invoke the user dialog as a subprocess
162 dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
163 process_command = [sys.executable, dlg_image, 'notification-' + args.msgtype, args.text]
164 process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
171 """OpenSecurity '/password' handler.
173 This is called on GET /password?text=TEXT.
174 Ideally this should pop up a user dialog to insert his
175 password based device name.
184 if not "text" in args:
185 raise web.badrequest('no text given')
188 remote_ip = web.ctx.environ['REMOTE_ADDR']
190 # create the process which queries the user
191 dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
192 process_command = [sys.executable, dlg_image, 'password', args.text]
193 process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
195 # run process result handling in seprate thread (not to block main one)
196 bouncer = UserResultBouncer(process, remote_ip, '/password')
199 return 'user queried for password'
204 """OpenSecurity '/' handler"""
208 res = "OpenSecurity-Client RESTFul Server { \"version\": \"%s\" }" % __version__
210 # add some sample links
216 (copy paste this into your browser's address field after the host:port)
218 /password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0)
220 (eg.: http://127.0.0.1:8090/password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0))
221 NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
224 Request a combination of user and password:
225 (copy paste this into your browser's address field after the host:port)
227 /credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.
229 (eg.: http://127.0.0.1:8090/credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.)
230 NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
233 Request a combination of password and keyfile:
234 (copy paste this into your browser's address field after the host:port)
236 /keyfile?text=Your%20private%20RSA%20Keyfile%3A
238 (eg.: http://127.0.0.1:8090//keyfile?text=Your%20private%20RSA%20Keyfile%3A)
239 NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
243 (copy paste this into your browser's address field after the host:port)
245 /application?vm=Debian+7&app=Browser
247 (e.g. http://127.0.0.1:8090/application?vm=Debian+7&app=Browser)
253 class UserResultBouncer(threading.Thread):
255 """A class to spawn off user I/O waiting and push the data back to the requesting services."""
257 def __init__(self, process, remote_ip, resource):
261 threading.Thread.__init__(self)
262 self._process = process
263 self._remote_ip = remote_ip
264 self._resource = resource
277 # invoke the user dialog as a subprocess
278 result = self._process.communicate()[0]
279 if self._process.returncode != 0:
280 print 'user request has been aborted.'
283 # all ok, tell send request back appropriate destination
285 j = json.loads(result)
287 print 'error in password parsing'
290 # TODO: it would be WAY easier and secure if we just
291 # add the result json to a HTTP-POST here.
292 url_addr = 'http://' + self._remote_ip + ':58080' + self._resource
293 url = url_addr + '?' + urllib.urlencode(j)
294 req = urllib2.Request(url)
296 res = urllib2.urlopen(req)
298 print 'failed to contact: ' + url_addr
303 if __name__ == "__main__":
304 server = web.application(opensecurity_urls, globals())