Statistics
| Branch: | Tag: | Revision:

root / vncauthproxy / client.py @ d3817d45

History | View | Annotate | Download (7.4 kB)

1 66d17b40 Apollon Oikonomopoulos
#!/usr/bin/env python
2 0c251ab5 Apollon Oikonomopoulos
#
3 7183f55d Faidon Liambotis
# Copyright (c) 2010-2011 Greek Research and Technology Network S.A.
4 0c251ab5 Apollon Oikonomopoulos
#
5 0c251ab5 Apollon Oikonomopoulos
# This program is free software; you can redistribute it and/or modify
6 0c251ab5 Apollon Oikonomopoulos
# it under the terms of the GNU General Public License as published by
7 0c251ab5 Apollon Oikonomopoulos
# the Free Software Foundation; either version 2 of the License, or
8 0c251ab5 Apollon Oikonomopoulos
# (at your option) any later version.
9 0c251ab5 Apollon Oikonomopoulos
#
10 0c251ab5 Apollon Oikonomopoulos
# This program is distributed in the hope that it will be useful, but
11 0c251ab5 Apollon Oikonomopoulos
# WITHOUT ANY WARRANTY; without even the implied warranty of
12 0c251ab5 Apollon Oikonomopoulos
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 0c251ab5 Apollon Oikonomopoulos
# General Public License for more details.
14 0c251ab5 Apollon Oikonomopoulos
#
15 0c251ab5 Apollon Oikonomopoulos
# You should have received a copy of the GNU General Public License
16 0c251ab5 Apollon Oikonomopoulos
# along with this program; if not, write to the Free Software
17 0c251ab5 Apollon Oikonomopoulos
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 0c251ab5 Apollon Oikonomopoulos
# 02110-1301, USA.
19 66d17b40 Apollon Oikonomopoulos
20 7f8ec5bd Stratos Psomadakis
""" vncauthproxy client """
21 7f8ec5bd Stratos Psomadakis
22 66d17b40 Apollon Oikonomopoulos
import sys
23 66d17b40 Apollon Oikonomopoulos
import socket
24 0b74ef50 Stratos Psomadakis
import ssl
25 66d17b40 Apollon Oikonomopoulos
26 48b1400e Vangelis Koukis
try:
27 48b1400e Vangelis Koukis
    import simplejson as json
28 48b1400e Vangelis Koukis
except ImportError:
29 48b1400e Vangelis Koukis
    import json
30 48b1400e Vangelis Koukis
31 b129b0c0 Stratos Psomadakis
try:
32 b129b0c0 Stratos Psomadakis
    from gevent import sleep
33 b129b0c0 Stratos Psomadakis
except ImportError:
34 7f8ec5bd Stratos Psomadakis
    from time import sleep
35 b129b0c0 Stratos Psomadakis
36 6f86c963 Stratos Psomadakis
import logging
37 6f86c963 Stratos Psomadakis
38 b129b0c0 Stratos Psomadakis
DEFAULT_SERVER_ADDRESS = '127.0.0.1'
39 b129b0c0 Stratos Psomadakis
DEFAULT_SERVER_PORT = 24999
40 66d17b40 Apollon Oikonomopoulos
41 6f86c963 Stratos Psomadakis
logger = logging.getLogger(__name__)
42 6f86c963 Stratos Psomadakis
43 31965126 Vangelis Koukis
44 03a592b9 Vangelis Koukis
def parse_arguments(args):
45 03a592b9 Vangelis Koukis
    from optparse import OptionParser
46 03a592b9 Vangelis Koukis
47 03a592b9 Vangelis Koukis
    parser = OptionParser()
48 b129b0c0 Stratos Psomadakis
    parser.add_option("--server", dest="server_address",
49 b129b0c0 Stratos Psomadakis
                      default=DEFAULT_SERVER_ADDRESS,
50 b129b0c0 Stratos Psomadakis
                      metavar="SERVER",
51 cf328b06 Stratos Psomadakis
                      help=("vncauthproxy server address"))
52 b129b0c0 Stratos Psomadakis
    parser.add_option("--server-port", dest="server_port",
53 b129b0c0 Stratos Psomadakis
                      default=DEFAULT_SERVER_PORT, type="int",
54 b129b0c0 Stratos Psomadakis
                      metavar="SERVER_PORT",
55 b129b0c0 Stratos Psomadakis
                      help=("vncauthproxy port"))
56 03a592b9 Vangelis Koukis
    parser.add_option('-s', dest="sport",
57 03a592b9 Vangelis Koukis
                      default=0, type="int",
58 03a592b9 Vangelis Koukis
                      metavar='PORT',
59 03a592b9 Vangelis Koukis
                      help=("Use source port PORT for incoming connections "
60 03a592b9 Vangelis Koukis
                            "(default: allocate a port automatically)"))
61 03a592b9 Vangelis Koukis
    parser.add_option("-d", "--dest",
62 03a592b9 Vangelis Koukis
                      default=None, dest="daddr",
63 03a592b9 Vangelis Koukis
                      metavar="HOST",
64 03a592b9 Vangelis Koukis
                      help="Proxy connection to destination host HOST")
65 03a592b9 Vangelis Koukis
    parser.add_option("-p", "--dport", dest="dport",
66 03a592b9 Vangelis Koukis
                      default=None, type="int",
67 03a592b9 Vangelis Koukis
                      metavar="PORT",
68 03a592b9 Vangelis Koukis
                      help="Proxy connection to destination port PORT")
69 03a592b9 Vangelis Koukis
    parser.add_option("-P", "--password", dest="password",
70 03a592b9 Vangelis Koukis
                      default=None,
71 03a592b9 Vangelis Koukis
                      metavar="PASSWORD",
72 03a592b9 Vangelis Koukis
                      help=("Use password PASSWD to authenticate incoming "
73 03a592b9 Vangelis Koukis
                            "VNC connections"))
74 d49bd2fb Stratos Psomadakis
    parser.add_option("--auth-user", dest="auth_user",
75 d49bd2fb Stratos Psomadakis
                      default=None,
76 d49bd2fb Stratos Psomadakis
                      metavar="AUTH_USER",
77 d49bd2fb Stratos Psomadakis
                      help=("User to authenticate as, for the control "
78 d49bd2fb Stratos Psomadakis
                            "connection"))
79 d49bd2fb Stratos Psomadakis
    parser.add_option("--auth-password", dest="auth_password",
80 d49bd2fb Stratos Psomadakis
                      default=None,
81 d49bd2fb Stratos Psomadakis
                      metavar="AUTH_PASSWORD",
82 d49bd2fb Stratos Psomadakis
                      help=("User password for the control connection "
83 d49bd2fb Stratos Psomadakis
                            "authentication"))
84 7f8ec5bd Stratos Psomadakis
    parser.add_option("--enable-ssl", dest="enable_ssl",
85 6149f03e Stratos Psomadakis
                      action='store_true', default=False,
86 7f8ec5bd Stratos Psomadakis
                      help=("Enable SSL/TLS for control connecions "
87 d49bd2fb Stratos Psomadakis
                            "(default: %s)" % False))
88 6149f03e Stratos Psomadakis
    parser.add_option("--ca-cert", dest="ca_cert",
89 6149f03e Stratos Psomadakis
                      default=None,
90 6149f03e Stratos Psomadakis
                      metavar="CACERT",
91 6149f03e Stratos Psomadakis
                      help=("CA certificate file to use for server auth"))
92 6149f03e Stratos Psomadakis
    parser.add_option("--strict", dest="strict",
93 6149f03e Stratos Psomadakis
                      default=False, action='store_true',
94 6149f03e Stratos Psomadakis
                      metavar="STRICT",
95 6149f03e Stratos Psomadakis
                      help=("Perform strict authentication on the server "
96 6149f03e Stratos Psomadakis
                            "SSL cert"))
97 03a592b9 Vangelis Koukis
98 03a592b9 Vangelis Koukis
    (opts, args) = parser.parse_args(args)
99 03a592b9 Vangelis Koukis
100 03a592b9 Vangelis Koukis
    return (opts, args)
101 03a592b9 Vangelis Koukis
102 03a592b9 Vangelis Koukis
103 03a592b9 Vangelis Koukis
def request_forwarding(sport, daddr, dport, password,
104 d49bd2fb Stratos Psomadakis
                       auth_user, auth_password,
105 b129b0c0 Stratos Psomadakis
                       server_address=DEFAULT_SERVER_ADDRESS,
106 7f8ec5bd Stratos Psomadakis
                       server_port=DEFAULT_SERVER_PORT, enable_ssl=False,
107 6149f03e Stratos Psomadakis
                       ca_cert=None, strict=False):
108 03a592b9 Vangelis Koukis
    """Connect to vncauthproxy and request a VNC forwarding."""
109 7f8ec5bd Stratos Psomadakis
110 7f8ec5bd Stratos Psomadakis
    # Mandatory arguments
111 03a592b9 Vangelis Koukis
    if not password:
112 7f8ec5bd Stratos Psomadakis
        raise Exception("The password argument is mandatory.")
113 7f8ec5bd Stratos Psomadakis
    if not daddr:
114 7f8ec5bd Stratos Psomadakis
        raise Exception("The daddr argument is mandatory.")
115 7f8ec5bd Stratos Psomadakis
    if not dport:
116 7f8ec5bd Stratos Psomadakis
        raise Exception("The dport argument is mandatory.")
117 7f8ec5bd Stratos Psomadakis
    if not auth_user:
118 7f8ec5bd Stratos Psomadakis
        raise Exception("The auth_user argument is mandatory.")
119 7f8ec5bd Stratos Psomadakis
    if not auth_password:
120 7f8ec5bd Stratos Psomadakis
        raise Exception("The auth_password argument is mandatory.")
121 7f8ec5bd Stratos Psomadakis
122 7f8ec5bd Stratos Psomadakis
    # Sanity check
123 7f8ec5bd Stratos Psomadakis
    if strict and not ca_cert:
124 7f8ec5bd Stratos Psomadakis
        raise Exception("strict requires ca-cert to be set")
125 7f8ec5bd Stratos Psomadakis
    if not enable_ssl and (strict or ca_cert):
126 6f86c963 Stratos Psomadakis
        logger.warning("strict or ca-cert set, but ssl not enabled")
127 03a592b9 Vangelis Koukis
128 48b1400e Vangelis Koukis
    req = {
129 48b1400e Vangelis Koukis
        "source_port": int(sport),
130 48b1400e Vangelis Koukis
        "destination_address": daddr,
131 48b1400e Vangelis Koukis
        "destination_port": int(dport),
132 b129b0c0 Stratos Psomadakis
        "password": password,
133 d49bd2fb Stratos Psomadakis
        "auth_user": auth_user,
134 d49bd2fb Stratos Psomadakis
        "auth_password": auth_password,
135 48b1400e Vangelis Koukis
    }
136 66d17b40 Apollon Oikonomopoulos
137 8b0f290d Stratos Psomadakis
    last_error = None
138 b129b0c0 Stratos Psomadakis
    retries = 5
139 b129b0c0 Stratos Psomadakis
    while retries:
140 b129b0c0 Stratos Psomadakis
        # Initiate server connection
141 b129b0c0 Stratos Psomadakis
        for res in socket.getaddrinfo(server_address, server_port,
142 b129b0c0 Stratos Psomadakis
                                      socket.AF_UNSPEC,
143 b129b0c0 Stratos Psomadakis
                                      socket.SOCK_STREAM, 0,
144 b129b0c0 Stratos Psomadakis
                                      socket.AI_PASSIVE):
145 b129b0c0 Stratos Psomadakis
            af, socktype, proto, canonname, sa = res
146 b129b0c0 Stratos Psomadakis
            try:
147 b129b0c0 Stratos Psomadakis
                server = socket.socket(af, socktype, proto)
148 b129b0c0 Stratos Psomadakis
            except socket.error:
149 b129b0c0 Stratos Psomadakis
                server = None
150 b129b0c0 Stratos Psomadakis
                continue
151 b129b0c0 Stratos Psomadakis
152 7f8ec5bd Stratos Psomadakis
            if enable_ssl:
153 6149f03e Stratos Psomadakis
                reqs = ssl.CERT_NONE
154 6149f03e Stratos Psomadakis
                if strict:
155 6149f03e Stratos Psomadakis
                    reqs = ssl.CERT_REQUIRED
156 6149f03e Stratos Psomadakis
                elif ca_cert:
157 6149f03e Stratos Psomadakis
                    reqs = ssl.CERT_OPTIONAL
158 6149f03e Stratos Psomadakis
159 7f8ec5bd Stratos Psomadakis
                server = ssl.wrap_socket(server, cert_reqs=reqs,
160 7f8ec5bd Stratos Psomadakis
                                         ca_certs=ca_cert,
161 7f8ec5bd Stratos Psomadakis
                                         ssl_version=ssl.PROTOCOL_TLSv1)
162 0b74ef50 Stratos Psomadakis
163 b129b0c0 Stratos Psomadakis
            server.settimeout(60.0)
164 b129b0c0 Stratos Psomadakis
165 b129b0c0 Stratos Psomadakis
            try:
166 b129b0c0 Stratos Psomadakis
                server.connect(sa)
167 8b0f290d Stratos Psomadakis
            except socket.error as err:
168 b129b0c0 Stratos Psomadakis
                server.close()
169 b129b0c0 Stratos Psomadakis
                server = None
170 d49bd2fb Stratos Psomadakis
                retries -= 1
171 8b0f290d Stratos Psomadakis
                last_error = err
172 b129b0c0 Stratos Psomadakis
                continue
173 b129b0c0 Stratos Psomadakis
174 b129b0c0 Stratos Psomadakis
            retries = 0
175 b129b0c0 Stratos Psomadakis
            break
176 b129b0c0 Stratos Psomadakis
177 b129b0c0 Stratos Psomadakis
        sleep(0.2)
178 b129b0c0 Stratos Psomadakis
179 b129b0c0 Stratos Psomadakis
    if server is None:
180 8b0f290d Stratos Psomadakis
        raise Exception("Failed to connect to server: %s" % last_error)
181 b129b0c0 Stratos Psomadakis
182 b129b0c0 Stratos Psomadakis
    server.send(json.dumps(req))
183 b129b0c0 Stratos Psomadakis
184 b129b0c0 Stratos Psomadakis
    response = server.recv(1024)
185 b129b0c0 Stratos Psomadakis
    server.close()
186 48b1400e Vangelis Koukis
    res = json.loads(response)
187 48b1400e Vangelis Koukis
    return res
188 66d17b40 Apollon Oikonomopoulos
189 03a592b9 Vangelis Koukis
190 66d17b40 Apollon Oikonomopoulos
if __name__ == '__main__':
191 6f86c963 Stratos Psomadakis
    logger.addHandler(logging.StreamHandler())
192 6f86c963 Stratos Psomadakis
193 03a592b9 Vangelis Koukis
    (opts, args) = parse_arguments(sys.argv[1:])
194 03a592b9 Vangelis Koukis
195 03a592b9 Vangelis Koukis
    res = request_forwarding(sport=opts.sport, daddr=opts.daddr,
196 d49bd2fb Stratos Psomadakis
                             dport=opts.dport, password=opts.password,
197 d49bd2fb Stratos Psomadakis
                             auth_user=opts.auth_user,
198 d49bd2fb Stratos Psomadakis
                             auth_password=opts.auth_password,
199 7f8ec5bd Stratos Psomadakis
                             enable_ssl=opts.enable_ssl, ca_cert=opts.ca_cert,
200 6149f03e Stratos Psomadakis
                             strict=opts.strict)
201 d49bd2fb Stratos Psomadakis
202 d49bd2fb Stratos Psomadakis
    reason = None
203 d49bd2fb Stratos Psomadakis
    if 'reason' in res:
204 d49bd2fb Stratos Psomadakis
        reason = 'Reason: %s\n' % res['reason']
205 d49bd2fb Stratos Psomadakis
    sys.stderr.write("Forwaring %s -> %s:%s: %s\n%s" % (res['source_port'],
206 7f8ec5bd Stratos Psomadakis
                                                        opts.daddr, opts.dport,
207 7f8ec5bd Stratos Psomadakis
                                                        res['status'], reason))
208 03a592b9 Vangelis Koukis
209 48b1400e Vangelis Koukis
    if res['status'] == "OK":
210 48b1400e Vangelis Koukis
        sys.exit(0)
211 48b1400e Vangelis Koukis
    else:
212 48b1400e Vangelis Koukis
        sys.exit(1)