Changeset 179
- Timestamp:
- 07/25/12 22:50:48 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
etherws/trunk/etherws.py
r178 r179 198 198 199 199 200 class Htpasswd(object): 201 def __init__(self, path): 202 self._path = path 203 self._stat = None 204 self._data = {} 205 206 def auth(self, name, passwd): 207 passwd = base64.b64encode(hashlib.sha1(passwd).digest()) 208 return self._data.get(name) == passwd 209 210 def load(self): 211 old_stat = self._stat 212 213 with open(self._path) as fp: 214 fileno = fp.fileno() 215 fcntl.flock(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB) 216 self._stat = os.fstat(fileno) 217 218 unchanged = old_stat and \ 219 old_stat.st_ino == self._stat.st_ino and \ 220 old_stat.st_dev == self._stat.st_dev and \ 221 old_stat.st_mtime == self._stat.st_mtime 222 223 if not unchanged: 224 self._data = self._parse(fp) 225 226 return self 227 228 def _parse(self, fp): 229 data = {} 230 for line in fp: 231 line = line.strip() 232 if 0 <= line.find(':'): 233 name, passwd = line.split(':', 1) 234 if passwd.startswith('{SHA}'): 235 data[name] = passwd[5:] 236 return data 237 238 200 239 class TapHandler(DebugMixIn): 201 240 READ_SIZE = 65535 … … 258 297 259 298 class EtherWebSocketHandler(tornado.websocket.WebSocketHandler, DebugMixIn): 260 def __init__(self, app, req, switch, debug=False):299 def __init__(self, app, req, switch, htpasswd=None, debug=False): 261 300 super(EtherWebSocketHandler, self).__init__(app, req) 262 301 self._switch = switch 302 self._htpasswd = htpasswd 263 303 self._debug = debug 304 305 if self._htpasswd: 306 self._htpasswd = Htpasswd(self._htpasswd) 264 307 265 308 def open(self): … … 273 316 self._switch.unregister_port(self) 274 317 self.dprintf('disconnected: %s\n', lambda: self.request.remote_ip) 318 319 def _execute(self, transforms, *args, **kwargs): 320 def do_execute(): 321 sp = super(EtherWebSocketHandler, self) 322 return sp._execute(transforms, *args, **kwargs) 323 324 def auth_required(): 325 self.stream.write(tornado.escape.utf8( 326 'HTTP/1.1 401 Authorization Required\r\n' 327 'WWW-Authenticate: Basic realm=etherws\r\n\r\n' 328 )) 329 self.stream.close() 330 331 try: 332 if not self._htpasswd: 333 return do_execute() 334 335 creds = self.request.headers.get('Authorization') 336 337 if not creds or not creds.startswith('Basic '): 338 return auth_required() 339 340 name, passwd = base64.b64decode(creds[6:]).split(':', 1) 341 342 if self._htpasswd.load().auth(name, passwd): 343 return do_execute() 344 except: 345 traceback.print_exc() 346 347 return auth_required() 275 348 276 349 … … 334 407 traceback.print_exc() 335 408 self.close() 336 337 338 class Htpasswd(object):339 def __init__(self, path):340 self._path = path341 self._stat = None342 self._data = {}343 344 def auth(self, name, passwd):345 passwd = base64.b64encode(hashlib.sha1(passwd).digest())346 return self._data.get(name) == passwd347 348 def load(self):349 old_stat = self._stat350 351 with open(self._path) as fp:352 fileno = fp.fileno()353 fcntl.flock(fileno, fcntl.LOCK_SH | fcntl.LOCK_NB)354 self._stat = os.fstat(fileno)355 356 unchanged = old_stat and \357 old_stat.st_ino == self._stat.st_ino and \358 old_stat.st_dev == self._stat.st_dev and \359 old_stat.st_mtime == self._stat.st_mtime360 361 if not unchanged:362 self._data = self._parse(fp)363 364 def _parse(self, fp):365 data = {}366 for line in fp:367 line = line.strip()368 if 0 <= line.find(':'):369 name, passwd = line.split(':', 1)370 if passwd.startswith('{SHA}'):371 data[name] = passwd[5:]372 return data373 374 375 def wrap_basic_auth(handler_class, htpasswd_path):376 if not htpasswd_path:377 return handler_class378 379 old_execute = handler_class._execute380 htpasswd = Htpasswd(htpasswd_path)381 382 def execute(self, transforms, *args, **kwargs):383 def auth_required():384 self.stream.write(tornado.escape.utf8(385 'HTTP/1.1 401 Authorization Required\r\n'386 'WWW-Authenticate: Basic realm=etherws\r\n\r\n'387 ))388 self.stream.close()389 390 creds = self.request.headers.get('Authorization')391 392 if not creds or not creds.startswith('Basic '):393 return auth_required()394 395 try:396 name, passwd = base64.b64decode(creds[6:]).split(':', 1)397 htpasswd.load()398 399 if not htpasswd.auth(name, passwd):400 return auth_required()401 402 return old_execute(self, transforms, *args, **kwargs)403 404 except:405 return auth_required()406 407 handler_class._execute = execute408 return handler_class409 409 410 410 … … 469 469 switch = SwitchingHub(fdb, debug=args.debug) 470 470 471 ha ndler = wrap_basic_auth(EtherWebSocketHandler, args.htpasswd)472 s rv = (args.path, handler, {'switch': switch, 'debug': args.debug})473 app = tornado.web.Application([s rv])471 harg = {'switch': switch, 'htpasswd': args.htpasswd, 'debug': args.debug} 472 serv = (args.path, EtherWebSocketHandler, harg) 473 app = tornado.web.Application([serv]) 474 474 server = tornado.httpserver.HTTPServer(app, ssl_options=ssl_options) 475 475 server.listen(args.port, address=args.address)
Note: See TracChangeset
for help on using the changeset viewer.