Revision b129b0c0
b/vncauthproxy/client.py | ||
---|---|---|
25 | 25 |
except ImportError: |
26 | 26 |
import json |
27 | 27 |
|
28 |
DEFAULT_CTRL_SOCKET = "/var/run/vncauthproxy/ctrl.sock" |
|
28 |
try: |
|
29 |
from gevent import sleep |
|
30 |
except ImportError: |
|
31 |
import sleep |
|
32 |
|
|
33 |
DEFAULT_SERVER_ADDRESS = '127.0.0.1' |
|
34 |
DEFAULT_SERVER_PORT = 24999 |
|
29 | 35 |
|
30 | 36 |
|
31 | 37 |
def parse_arguments(args): |
32 | 38 |
from optparse import OptionParser |
33 | 39 |
|
34 | 40 |
parser = OptionParser() |
35 |
parser.add_option("-c", "--socket", dest="ctrl_socket", |
|
36 |
default=DEFAULT_CTRL_SOCKET, |
|
37 |
metavar="PATH", |
|
38 |
help=("UNIX socket for connecting to vncauthproxy " |
|
39 |
"(default: %s)" % DEFAULT_CTRL_SOCKET)) |
|
41 |
parser.add_option("--server", dest="server_address", |
|
42 |
default=DEFAULT_SERVER_ADDRESS, |
|
43 |
metavar="SERVER", |
|
44 |
help=("vncauthproxy server")) |
|
45 |
parser.add_option("--server-port", dest="server_port", |
|
46 |
default=DEFAULT_SERVER_PORT, type="int", |
|
47 |
metavar="SERVER_PORT", |
|
48 |
help=("vncauthproxy port")) |
|
40 | 49 |
parser.add_option('-s', dest="sport", |
41 | 50 |
default=0, type="int", |
42 | 51 |
metavar='PORT', |
... | ... | |
59 | 68 |
(opts, args) = parser.parse_args(args) |
60 | 69 |
|
61 | 70 |
# Mandatory arguments |
71 |
if not opts.server_address: |
|
72 |
parser.error("The --server argument is mandatory.") |
|
62 | 73 |
if not opts.password: |
63 | 74 |
parser.error("The -P/--password argument is mandatory.") |
64 | 75 |
if not opts.daddr: |
... | ... | |
70 | 81 |
|
71 | 82 |
|
72 | 83 |
def request_forwarding(sport, daddr, dport, password, |
73 |
ctrl_socket=DEFAULT_CTRL_SOCKET): |
|
84 |
server_address=DEFAULT_SERVER_ADDRESS, |
|
85 |
server_port=DEFAULT_SERVER_PORT): |
|
74 | 86 |
"""Connect to vncauthproxy and request a VNC forwarding.""" |
75 | 87 |
if not password: |
76 | 88 |
raise ValueError("You must specify a non-empty password") |
... | ... | |
79 | 91 |
"source_port": int(sport), |
80 | 92 |
"destination_address": daddr, |
81 | 93 |
"destination_port": int(dport), |
82 |
"password": password |
|
94 |
"password": password,
|
|
83 | 95 |
} |
84 | 96 |
|
85 |
ctrl = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
|
86 |
ctrl.connect(ctrl_socket) |
|
87 |
ctrl.send(json.dumps(req)) |
|
88 |
|
|
89 |
response = ctrl.recv(1024) |
|
97 |
retries = 5 |
|
98 |
while retries: |
|
99 |
# Initiate server connection |
|
100 |
for res in socket.getaddrinfo(server_address, server_port, |
|
101 |
socket.AF_UNSPEC, |
|
102 |
socket.SOCK_STREAM, 0, |
|
103 |
socket.AI_PASSIVE): |
|
104 |
af, socktype, proto, canonname, sa = res |
|
105 |
try: |
|
106 |
server = socket.socket(af, socktype, proto) |
|
107 |
except socket.error: |
|
108 |
server = None |
|
109 |
continue |
|
110 |
|
|
111 |
server.settimeout(60.0) |
|
112 |
|
|
113 |
try: |
|
114 |
server.connect(sa) |
|
115 |
except socket.error: |
|
116 |
server.close() |
|
117 |
server = None |
|
118 |
continue |
|
119 |
|
|
120 |
retries = 0 |
|
121 |
break |
|
122 |
|
|
123 |
sleep(0.2) |
|
124 |
|
|
125 |
if server is None: |
|
126 |
raise Exception("Failed to connect to server") |
|
127 |
|
|
128 |
server.send(json.dumps(req)) |
|
129 |
|
|
130 |
response = server.recv(1024) |
|
131 |
server.close() |
|
90 | 132 |
res = json.loads(response) |
91 | 133 |
return res |
92 | 134 |
|
... | ... | |
95 | 137 |
(opts, args) = parse_arguments(sys.argv[1:]) |
96 | 138 |
|
97 | 139 |
res = request_forwarding(sport=opts.sport, daddr=opts.daddr, |
98 |
dport=opts.dport, password=opts.password, |
|
99 |
ctrl_socket=opts.ctrl_socket) |
|
140 |
dport=opts.dport, password=opts.password) |
|
100 | 141 |
|
101 | 142 |
sys.stderr.write("Forwaring %s -> %s:%s: %s\n" % (res['source_port'], |
102 | 143 |
opts.daddr, opts.dport, |
b/vncauthproxy/proxy.py | ||
---|---|---|
20 | 20 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
21 | 21 |
# 02110-1301, USA. |
22 | 22 |
|
23 |
DEFAULT_CTRL_SOCKET = "/var/run/vncauthproxy/ctrl.sock" |
|
23 |
DEFAULT_BIND_ADDRESS = None |
|
24 |
DEFAULT_LPORT = 24999 |
|
24 | 25 |
DEFAULT_LOG_FILE = "/var/log/vncauthproxy/vncauthproxy.log" |
25 | 26 |
DEFAULT_PID_FILE = "/var/run/vncauthproxy/vncauthproxy.pid" |
26 | 27 |
DEFAULT_CONNECT_TIMEOUT = 30 |
... | ... | |
453 | 454 |
from optparse import OptionParser |
454 | 455 |
|
455 | 456 |
parser = OptionParser() |
456 |
parser.add_option("-s", "--socket", dest="ctrl_socket", |
|
457 |
default=DEFAULT_CTRL_SOCKET, |
|
458 |
metavar="PATH", |
|
459 |
help=("UNIX socket for control connections (default: " |
|
460 |
"%s" % DEFAULT_CTRL_SOCKET)) |
|
457 |
parser.add_option("--bind", dest="bind_address", |
|
458 |
default=DEFAULT_BIND_ADDRESS, |
|
459 |
metavar="ADDRESS", |
|
460 |
help=("Address to listen for control connections")) |
|
461 |
parser.add_option( "--lport", dest="lport", |
|
462 |
default=DEFAULT_LPORT, |
|
463 |
metavar="LPORT", |
|
464 |
help=("Port to listen for control connections")) |
|
461 | 465 |
parser.add_option("-d", "--debug", action="store_true", dest="debug", |
462 | 466 |
help="Enable debugging information") |
463 | 467 |
parser.add_option("-l", "--log", dest="log_file", |
... | ... | |
648 | 652 |
# we *must* reinit gevent |
649 | 653 |
gevent.reinit() |
650 | 654 |
|
651 |
if os.path.exists(opts.ctrl_socket): |
|
652 |
logger.critical("Socket '%s' already exists", opts.ctrl_socket) |
|
653 |
sys.exit(1) |
|
654 |
|
|
655 |
# TODO: make this tunable? chgrp as well? |
|
656 |
old_umask = os.umask(0007) |
|
657 |
|
|
658 |
ctrl = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
|
659 |
ctrl.bind(opts.ctrl_socket) |
|
660 |
|
|
661 |
os.umask(old_umask) |
|
655 |
sockets = [] |
|
656 |
for res in socket.getaddrinfo(opts.bind_address, opts.lport, |
|
657 |
socket.AF_UNSPEC, socket.SOCK_STREAM, 0, |
|
658 |
socket.AI_PASSIVE): |
|
659 |
af, socktype, proto, canonname, sa = res |
|
660 |
try: |
|
661 |
s = None |
|
662 |
s = socket.socket(af, socktype, proto) |
|
663 |
if af == socket.AF_INET6: |
|
664 |
# Bind v6 only when AF_INET6, otherwise either v4 or v6 bind |
|
665 |
# will fail. |
|
666 |
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) |
|
667 |
s.bind(sa) |
|
668 |
s.listen(opts.backlog) |
|
669 |
sockets.append(s) |
|
670 |
logger.info("Control socket listening on %s:%d", *sa[:2]) |
|
671 |
except socket.error, msg: |
|
672 |
logger.critical("Error binding control socket to %s:%d: %s", |
|
673 |
sa[0], sa[1], msg[1]) |
|
674 |
if s: |
|
675 |
s.close() |
|
676 |
while sockets: |
|
677 |
sockets.pop.close() |
|
662 | 678 |
|
663 |
ctrl.listen(opts.backlog) |
|
664 |
logger.info("Initialized, waiting for control connections at %s", |
|
665 |
opts.ctrl_socket) |
|
679 |
sys.exit(1) |
|
666 | 680 |
|
667 | 681 |
# Catch signals to ensure graceful shutdown, |
668 | 682 |
# e.g., to make sure the control socket gets unlink()ed. |
... | ... | |
677 | 691 |
|
678 | 692 |
while True: |
679 | 693 |
try: |
680 |
client, addr = ctrl.accept() |
|
681 |
logger.info("New control connection") |
|
694 |
rlist, _, _ = select(sockets, [], []) |
|
695 |
for ctrl in rlist: |
|
696 |
client, addr = ctrl.accept() |
|
697 |
logger.info("New control connection") |
|
682 | 698 |
|
683 |
gevent.Greenlet.spawn(establish_connection, client, addr, |
|
684 |
ports, opts) |
|
699 |
gevent.Greenlet.spawn(establish_connection, client, addr,
|
|
700 |
ports, opts)
|
|
685 | 701 |
except Exception, e: |
686 | 702 |
logger.exception(e) |
687 | 703 |
continue |
688 | 704 |
except SystemExit: |
689 | 705 |
break |
690 | 706 |
|
691 |
logger.info("Unlinking control socket at %s", opts.ctrl_socket) |
|
692 |
os.unlink(opts.ctrl_socket) |
|
707 |
logger.info("Closing control sockets") |
|
708 |
while sockets: |
|
709 |
sockets.pop.close() |
|
693 | 710 |
daemon_context.close() |
694 | 711 |
sys.exit(0) |
Also available in: Unified diff