Statistics
| Branch: | Tag: | Revision:

root / vncauthproxy / client.py @ 0b74ef50

History | View | Annotate | Download (5 kB)

1
#!/usr/bin/env python
2
#
3
# Copyright (c) 2010-2011 Greek Research and Technology Network S.A.
4
#
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
# General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
# 02110-1301, USA.
19

    
20
import sys
21
import socket
22
import ssl
23

    
24
try:
25
    import simplejson as json
26
except ImportError:
27
    import json
28

    
29
try:
30
    from gevent import sleep
31
except ImportError:
32
    import sleep
33

    
34
DEFAULT_SERVER_ADDRESS = '127.0.0.1'
35
DEFAULT_SERVER_PORT = 24999
36

    
37

    
38
def parse_arguments(args):
39
    from optparse import OptionParser
40

    
41
    parser = OptionParser()
42
    parser.add_option("--server", dest="server_address",
43
                      default=DEFAULT_SERVER_ADDRESS,
44
                      metavar="SERVER",
45
                      help=("vncauthproxy server address"))
46
    parser.add_option("--server-port", dest="server_port",
47
                      default=DEFAULT_SERVER_PORT, type="int",
48
                      metavar="SERVER_PORT",
49
                      help=("vncauthproxy port"))
50
    parser.add_option('-s', dest="sport",
51
                      default=0, type="int",
52
                      metavar='PORT',
53
                      help=("Use source port PORT for incoming connections "
54
                            "(default: allocate a port automatically)"))
55
    parser.add_option("-d", "--dest",
56
                      default=None, dest="daddr",
57
                      metavar="HOST",
58
                      help="Proxy connection to destination host HOST")
59
    parser.add_option("-p", "--dport", dest="dport",
60
                      default=None, type="int",
61
                      metavar="PORT",
62
                      help="Proxy connection to destination port PORT")
63
    parser.add_option("-P", "--password", dest="password",
64
                      default=None,
65
                      metavar="PASSWORD",
66
                      help=("Use password PASSWD to authenticate incoming "
67
                            "VNC connections"))
68

    
69
    (opts, args) = parser.parse_args(args)
70

    
71
    # Mandatory arguments
72
    if not opts.password:
73
        parser.error("The -P/--password argument is mandatory.")
74
    if not opts.daddr:
75
        parser.error("The -d/--dest argument is mandatory.")
76
    if not opts.dport:
77
        parser.error("The -p/--dport argument is mandatory.")
78

    
79
    return (opts, args)
80

    
81

    
82
def request_forwarding(sport, daddr, dport, password,
83
                       server_address=DEFAULT_SERVER_ADDRESS,
84
                       server_port=DEFAULT_SERVER_PORT, ssl_sock=True):
85
    """Connect to vncauthproxy and request a VNC forwarding."""
86
    if not password:
87
        raise ValueError("You must specify a non-empty password")
88

    
89
    req = {
90
        "source_port": int(sport),
91
        "destination_address": daddr,
92
        "destination_port": int(dport),
93
        "password": password,
94
    }
95

    
96
    retries = 5
97
    while retries:
98
        # Initiate server connection
99
        for res in socket.getaddrinfo(server_address, server_port,
100
                                      socket.AF_UNSPEC,
101
                                      socket.SOCK_STREAM, 0,
102
                                      socket.AI_PASSIVE):
103
            af, socktype, proto, canonname, sa = res
104
            try:
105
                server = socket.socket(af, socktype, proto)
106
            except socket.error:
107
                server = None
108
                continue
109

    
110
            if ssl_sock:
111
                server = ssl.wrap_socket(
112
                      server, cert_reqs=ssl.CERT_NONE,
113
                      ssl_version=ssl.PROTOCOL_TLSv1)
114

    
115
            server.settimeout(60.0)
116

    
117
            try:
118
                server.connect(sa)
119
            except socket.error:
120
                server.close()
121
                server = None
122
                continue
123

    
124
            retries = 0
125
            break
126

    
127
        sleep(0.2)
128

    
129
    if server is None:
130
        raise Exception("Failed to connect to server")
131

    
132
    server.send(json.dumps(req))
133

    
134
    response = server.recv(1024)
135
    server.close()
136
    res = json.loads(response)
137
    return res
138

    
139

    
140
if __name__ == '__main__':
141
    (opts, args) = parse_arguments(sys.argv[1:])
142

    
143
    res = request_forwarding(sport=opts.sport, daddr=opts.daddr,
144
                             dport=opts.dport, password=opts.password)
145

    
146
    sys.stderr.write("Forwaring %s -> %s:%s: %s\n" % (res['source_port'],
147
                                                      opts.daddr, opts.dport,
148
                                                      res['status']))
149

    
150
    if res['status'] == "OK":
151
        sys.exit(0)
152
    else:
153
        sys.exit(1)