Revision 4af60ef0
b/vncauthproxy/vncauthproxy.py | ||
---|---|---|
18 | 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
19 | 19 |
# 02110-1301, USA. |
20 | 20 |
|
21 |
DEFAULT_CTRL_SOCKET = "/tmp/vncproxy.sock" |
|
22 |
DEFAULT_LOG_FILE = "/var/log/vncauthproxy/vncauthproxy.log" |
|
23 |
DEFAULT_PID_FILE = "/var/run/vncauthproxy/vncauthproxy.pid" |
|
24 |
DEFAULT_CONNECT_TIMEOUT = 30 |
|
21 | 25 |
|
22 | 26 |
import os |
23 | 27 |
import sys |
24 | 28 |
import logging |
25 | 29 |
import gevent |
30 |
import daemon |
|
31 |
import daemon.pidlockfile |
|
26 | 32 |
|
27 | 33 |
import rfb |
28 | 34 |
|
29 | 35 |
from gevent import socket |
30 |
from signal import SIGTERM |
|
36 |
from signal import SIGINT, SIGTERM
|
|
31 | 37 |
from gevent import signal |
32 | 38 |
from gevent.select import select |
33 | 39 |
|
... | ... | |
48 | 54 |
""" |
49 | 55 |
id = 1 |
50 | 56 |
|
51 |
def __init__(self, sport, daddr, dport, password, connect_timeout=30):
|
|
57 |
def __init__(self, logger, sport, daddr, dport, password, connect_timeout):
|
|
52 | 58 |
""" |
59 |
@type logger: logging.Logger |
|
60 |
@param logger: the logger to use |
|
53 | 61 |
@type sport: int |
54 | 62 |
@param sport: source port |
55 | 63 |
@type daddr: str |
... | ... | |
70 | 78 |
self.daddr = daddr |
71 | 79 |
self.dport = dport |
72 | 80 |
self.password = password |
73 |
self.log = logging
|
|
81 |
self.log = logger
|
|
74 | 82 |
self.server = None |
75 | 83 |
self.client = None |
76 | 84 |
self.timeout = connect_timeout |
... | ... | |
84 | 92 |
raise gevent.GreenletExit |
85 | 93 |
|
86 | 94 |
def info(self, msg): |
87 |
logging.info("[C%d] %s" % (self.id, msg))
|
|
95 |
self.log.info("[C%d] %s" % (self.id, msg))
|
|
88 | 96 |
|
89 | 97 |
def debug(self, msg): |
90 |
logging.debug("[C%d] %s" % (self.id, msg))
|
|
98 |
self.log.debug("[C%d] %s" % (self.id, msg))
|
|
91 | 99 |
|
92 | 100 |
def warn(self, msg): |
93 |
logging.warn("[C%d] %s" % (self.id, msg))
|
|
101 |
self.log.warn("[C%d] %s" % (self.id, msg))
|
|
94 | 102 |
|
95 | 103 |
def error(self, msg): |
96 |
logging.error("[C%d] %s" % (self.id, msg))
|
|
104 |
self.log.error("[C%d] %s" % (self.id, msg))
|
|
97 | 105 |
|
98 | 106 |
def critical(self, msg): |
99 |
logging.critical("[C%d] %s" % (self.id, msg))
|
|
107 |
self.log.critical("[C%d] %s" % (self.id, msg))
|
|
100 | 108 |
|
101 | 109 |
def __str__(self): |
102 | 110 |
return "VncAuthProxy: %d -> %s:%d" % (self.sport, self.daddr, self.dport) |
... | ... | |
313 | 321 |
|
314 | 322 |
|
315 | 323 |
def fatal_signal_handler(signame): |
316 |
logging.info("Caught %s, will raise SystemExit" % signame)
|
|
324 |
logger.info("Caught %s, will raise SystemExit" % signame)
|
|
317 | 325 |
raise SystemExit |
318 | 326 |
|
319 | 327 |
|
... | ... | |
322 | 330 |
|
323 | 331 |
parser = OptionParser() |
324 | 332 |
parser.add_option("-s", "--socket", dest="ctrl_socket", |
325 |
help="UNIX socket path for control connections", |
|
326 |
default="/tmp/vncproxy.sock", |
|
327 |
metavar="PATH") |
|
333 |
default=DEFAULT_CTRL_SOCKET, |
|
334 |
metavar="PATH", |
|
335 |
help="UNIX socket path for control connections (default: %s" % |
|
336 |
DEFAULT_CTRL_SOCKET) |
|
328 | 337 |
parser.add_option("-d", "--debug", action="store_true", dest="debug", |
329 | 338 |
help="Enable debugging information") |
330 |
parser.add_option("-l", "--log", dest="logfile", default=None, |
|
331 |
help="Write log to FILE instead of stdout", |
|
332 |
metavar="FILE") |
|
339 |
parser.add_option("-l", "--log", dest="log_file", |
|
340 |
default=DEFAULT_LOG_FILE, |
|
341 |
metavar="FILE", |
|
342 |
help="Write log to FILE instead of %s" % DEFAULT_LOG_FILE), |
|
343 |
parser.add_option('--pid-file', dest="pid_file", |
|
344 |
default=DEFAULT_PID_FILE, |
|
345 |
metavar='PIDFILE', |
|
346 |
help="Save PID to file (default: %s)" % |
|
347 |
DEFAULT_PID_FILE) |
|
333 | 348 |
parser.add_option("-t", "--connect-timeout", dest="connect_timeout", |
334 |
default=30, type="int", metavar="SECONDS",
|
|
349 |
default=DEFAULT_CONNECT_TIMEOUT, type="int", metavar="SECONDS",
|
|
335 | 350 |
help="How long to listen for clients to forward") |
336 | 351 |
|
337 | 352 |
(opts, args) = parser.parse_args(sys.argv[1:]) |
338 | 353 |
|
354 |
# Create pidfile |
|
355 |
pidf = daemon.pidlockfile.TimeoutPIDLockFile( |
|
356 |
opts.pid_file, 10) |
|
357 |
|
|
358 |
# Initialize logger |
|
339 | 359 |
lvl = logging.DEBUG if opts.debug else logging.INFO |
340 |
|
|
341 |
logging.basicConfig(level=lvl, filename=opts.logfile, |
|
342 |
format="%(asctime)s %(levelname)s: %(message)s", |
|
343 |
datefmt="%m/%d/%Y %H:%M:%S") |
|
360 |
logger = logging.getLogger("vncauthproxy") |
|
361 |
logger.setLevel(lvl) |
|
362 |
formatter = logging.Formatter("%(asctime)s vncauthproxy[%(process)d] %(levelname)s: %(message)s", |
|
363 |
"%Y-%m-%d %H:%M:%S") |
|
364 |
handler = logging.FileHandler(opts.log_file) |
|
365 |
handler.setFormatter(formatter) |
|
366 |
logger.addHandler(handler) |
|
367 |
|
|
368 |
# Become a daemon |
|
369 |
# Redirecting stdout and stderr to handler.stream to catch |
|
370 |
# early errors in the daemonization process [e.g., pidfile creation] |
|
371 |
# which will otherwise go to /dev/null. |
|
372 |
daemon_context = daemon.DaemonContext( |
|
373 |
pidfile=pidf, |
|
374 |
umask=0o0022, |
|
375 |
stdout=handler.stream, |
|
376 |
stderr=handler.stream, |
|
377 |
files_preserve=[handler.stream]) |
|
378 |
daemon_context.open() |
|
379 |
logger.info("Became a daemon") |
|
380 |
|
|
381 |
# A fork() has occured while daemonizing, |
|
382 |
# we *must* reinit gevent |
|
383 |
gevent.reinit() |
|
344 | 384 |
|
345 | 385 |
if os.path.exists(opts.ctrl_socket): |
346 |
logging.critical("Socket '%s' already exists" % opts.ctrl_socket)
|
|
386 |
logger.critical("Socket '%s' already exists" % opts.ctrl_socket)
|
|
347 | 387 |
sys.exit(1) |
348 | 388 |
|
349 | 389 |
# TODO: make this tunable? chgrp as well? |
... | ... | |
355 | 395 |
os.umask(old_umask) |
356 | 396 |
|
357 | 397 |
ctrl.listen(1) |
358 |
logging.info("Initalized, waiting for control connections at %s" %
|
|
398 |
logger.info("Initialized, waiting for control connections at %s" %
|
|
359 | 399 |
opts.ctrl_socket) |
360 | 400 |
|
361 |
# Catch SIGTERM to ensure graceful shutdown,
|
|
401 |
# Catch signals to ensure graceful shutdown,
|
|
362 | 402 |
# e.g., to make sure the control socket gets unlink()ed. |
363 | 403 |
# |
364 | 404 |
# Uses gevent.signal so the handler fires even during |
365 | 405 |
# gevent.socket.accept() |
406 |
gevent.signal(SIGINT, fatal_signal_handler, "SIGINT") |
|
366 | 407 |
gevent.signal(SIGTERM, fatal_signal_handler, "SIGTERM") |
367 |
|
|
368 | 408 |
while True: |
369 | 409 |
try: |
370 | 410 |
client, addr = ctrl.accept() |
371 |
except (KeyboardInterrupt, SystemExit):
|
|
411 |
except SystemExit:
|
|
372 | 412 |
break |
373 | 413 |
|
374 |
logging.info("New control connection")
|
|
414 |
logger.info("New control connection")
|
|
375 | 415 |
line = client.recv(1024).strip() |
376 | 416 |
try: |
377 | 417 |
# Control message format: |
... | ... | |
382 | 422 |
# connecting to <source_port>, who will subsequently be forwarded |
383 | 423 |
# to a VNC server at <destination_address>:<destination_port> |
384 | 424 |
sport, daddr, dport, password = line.split(':', 3) |
385 |
logging.info("New forwarding [%d -> %s:%d]" %
|
|
425 |
logger.info("New forwarding [%d -> %s:%d]" %
|
|
386 | 426 |
(int(sport), daddr, int(dport))) |
387 | 427 |
except: |
388 |
logging.warn("Malformed request: %s" % line)
|
|
428 |
logger.warn("Malformed request: %s" % line)
|
|
389 | 429 |
client.send("FAILED\n") |
390 | 430 |
client.close() |
391 | 431 |
continue |
392 | 432 |
|
393 | 433 |
client.send("OK\n") |
394 |
VncAuthProxy.spawn(sport, daddr, dport, password, opts.connect_timeout) |
|
434 |
VncAuthProxy.spawn(logger, sport, daddr, dport, password, opts.connect_timeout)
|
|
395 | 435 |
client.close() |
396 | 436 |
|
397 |
logging.info("Unlinking control socket at %s" %
|
|
437 |
logger.info("Unlinking control socket at %s" %
|
|
398 | 438 |
opts.ctrl_socket) |
399 | 439 |
os.unlink(opts.ctrl_socket) |
440 |
daemon_context.close() |
|
400 | 441 |
sys.exit(0) |
Also available in: Unified diff