• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6
7from autotest_lib.client.bin import utils
8from autotest_lib.client.cros import network_chroot
9from autotest_lib.client.common_lib.cros import site_eap_certs
10
11class VPNServer(object):
12    """Context enclosing the use of a VPN server instance."""
13
14    def __enter__(self):
15        self.start_server()
16        return self
17
18
19    def __exit__(self, exception, value, traceback):
20        logging.info('Log contents: %s', self.get_log_contents())
21        self.stop_server()
22
23
24class L2TPIPSecVPNServer(VPNServer):
25    """Implementation of an L2TP/IPSec VPN.  Uses ipsec starter and xl2tpd."""
26    PRELOAD_MODULES = ('af_key', 'ah4', 'esp4', 'ipcomp', 'xfrm_user',
27                       'xfrm4_tunnel')
28    ROOT_DIRECTORIES = ('etc/ipsec.d', 'etc/ipsec.d/cacerts',
29                        'etc/ipsec.d/certs', 'etc/ipsec.d/crls',
30                        'etc/ipsec.d/private', 'etc/ppp', 'etc/xl2tpd')
31    CHAP_USER = 'chapuser'
32    CHAP_SECRET = 'chapsecret'
33    IPSEC_COMMAND = '/usr/sbin/ipsec'
34    IPSEC_LOGFILE = 'var/log/charon.log'
35    IPSEC_PRESHARED_KEY = 'preshared-key'
36    IPSEC_CA_CERTIFICATE = 'etc/ipsec.d/cacerts/ca.cert'
37    IPSEC_SERVER_CERTIFICATE = 'etc/ipsec.d/certs/server.cert'
38    PPPD_PID_FILE = 'run/ppp0.pid'
39    XAUTH_USER = 'xauth_user'
40    XAUTH_PASSWORD = 'xauth_password'
41    XAUTH_SECONDARY_AUTHENTICATION_STANZA = 'rightauth2=xauth'
42    XL2TPD_COMMAND = '/usr/sbin/xl2tpd'
43    XL2TPD_CONFIG_FILE = 'etc/xl2tpd/xl2tpd.conf'
44    XL2TPD_PID_FILE = 'run/xl2tpd.pid'
45    SERVER_IP_ADDRESS = '192.168.1.99'
46    IPSEC_COMMON_CONFIGS = {
47        'etc/strongswan.conf' :
48            'charon {\n'
49            '  filelog {\n'
50            '    %(charon-logfile)s {\n'
51            '      time_format = %%b %%e %%T\n'
52            '      default = 3\n'
53            '    }\n'
54            '  }\n'
55            '  install_routes = no\n'
56            '  ignore_routing_tables = 0\n'
57            '  routing_table = 0\n'
58            '}\n',
59
60        'etc/passwd' :
61            'root:x:0:0:root:/root:/bin/bash\n'
62            'ipsec:*:212:212::/dev/null:/bin/false\n',
63
64        'etc/group' :
65            'ipsec:x:212:\n',
66
67        XL2TPD_CONFIG_FILE :
68            '[global]\n'
69            '\n'
70            '[lns default]\n'
71            '  ip range = 192.168.1.128-192.168.1.254\n'
72            '  local ip = 192.168.1.99\n'
73            '  require chap = yes\n'
74            '  refuse pap = yes\n'
75            '  require authentication = yes\n'
76            '  name = LinuxVPNserver\n'
77            '  ppp debug = yes\n'
78            '  pppoptfile = /etc/ppp/options.xl2tpd\n'
79            '  length bit = yes\n',
80
81        'etc/xl2tpd/l2tp-secrets' :
82            '*      them    l2tp-secret',
83
84        'etc/ppp/chap-secrets' :
85            '%(chap-user)s        *       %(chap-secret)s      *',
86
87        'etc/ppp/options.xl2tpd' :
88            'ipcp-accept-local\n'
89            'ipcp-accept-remote\n'
90            'noccp\n'
91            'auth\n'
92            'crtscts\n'
93            'idle 1800\n'
94            'mtu 1410\n'
95            'mru 1410\n'
96            'nodefaultroute\n'
97            'debug\n'
98            'lock\n'
99            'proxyarp\n'
100    }
101    IPSEC_TYPED_CONFIGS = {
102        'psk': {
103            'etc/ipsec.conf' :
104                'config setup\n'
105                '  charondebug="%(charon-debug-flags)s"\n'
106                'conn L2TP\n'
107                '  keyexchange=ikev1\n'
108                '  ike=aes128-sha1-modp2048!\n'
109                '  esp=3des-sha1!\n'
110                '  type=transport\n'
111                '  authby=psk\n'
112                '  %(xauth-stanza)s\n'
113                '  rekey=no\n'
114                '  left=%(local-ip)s\n'
115                '  leftprotoport=17/1701\n'
116                '  right=%%any\n'
117                '  rightprotoport=17/%%any\n'
118                '  auto=add\n',
119
120            'etc/ipsec.secrets' :
121              '%(local-ip)s %%any : PSK "%(preshared-key)s"\n'
122              '%(xauth-user)s : XAUTH "%(xauth-password)s"\n',
123        },
124        'cert': {
125            'etc/ipsec.conf' :
126                'config setup\n'
127                '  charondebug="%(charon-debug-flags)s"\n'
128                'conn L2TP\n'
129                '  keyexchange=ikev1\n'
130                '  ike=aes128-sha1-modp2048!\n'
131                '  esp=3des-sha1!\n'
132                '  type=transport\n'
133                '  left=%(local-ip)s\n'
134                '  leftcert=server.cert\n'
135                '  leftid="C=US, ST=California, L=Mountain View, '
136                'CN=chromelab-wifi-testbed-server.mtv.google.com"\n'
137                '  leftprotoport=17/1701\n'
138                '  right=%%any\n'
139                '  rightca="C=US, ST=California, L=Mountain View, '
140                'CN=chromelab-wifi-testbed-root.mtv.google.com"\n'
141                '  rightprotoport=17/%%any\n'
142                '  auto=add\n',
143
144            'etc/ipsec.secrets' : ': RSA server.key ""\n',
145
146            IPSEC_SERVER_CERTIFICATE : site_eap_certs.server_cert_1,
147            IPSEC_CA_CERTIFICATE : site_eap_certs.ca_cert_1,
148            'etc/ipsec.d/private/server.key' :
149                site_eap_certs.server_private_key_1,
150        },
151    }
152
153    """Implementation of an L2TP/IPSec server instance."""
154    def __init__(self, auth_type, interface_name, address, network_prefix,
155                 perform_xauth_authentication=False,
156                 local_ip_is_public_ip=False):
157        self._auth_type = auth_type
158        self._chroot = network_chroot.NetworkChroot(interface_name,
159                                                    address, network_prefix)
160        self._perform_xauth_authentication = perform_xauth_authentication
161
162        if local_ip_is_public_ip:
163            self.IPSEC_COMMON_CONFIGS[self.XL2TPD_CONFIG_FILE] = \
164                self.IPSEC_COMMON_CONFIGS[self.XL2TPD_CONFIG_FILE].replace(
165                    self.SERVER_IP_ADDRESS, address)
166            self.SERVER_IP_ADDRESS = address
167
168
169    def start_server(self):
170        """Start VPN server instance"""
171        if self._auth_type not in self.IPSEC_TYPED_CONFIGS:
172            raise RuntimeError('L2TP/IPSec type %s is not define' %
173                               self._auth_type)
174        chroot = self._chroot
175        chroot.add_root_directories(self.ROOT_DIRECTORIES)
176        chroot.add_config_templates(self.IPSEC_COMMON_CONFIGS)
177        chroot.add_config_templates(self.IPSEC_TYPED_CONFIGS[self._auth_type])
178        chroot.add_config_values({
179            'chap-user': self.CHAP_USER,
180            'chap-secret': self.CHAP_SECRET,
181            'charon-debug-flags': 'dmn 2, mgr 2, ike 2, net 2',
182            'charon-logfile': self.IPSEC_LOGFILE,
183            'preshared-key': self.IPSEC_PRESHARED_KEY,
184            'xauth-user': self.XAUTH_USER,
185            'xauth-password': self.XAUTH_PASSWORD,
186            'xauth-stanza': self.XAUTH_SECONDARY_AUTHENTICATION_STANZA
187                    if self._perform_xauth_authentication else '',
188        })
189        chroot.add_startup_command('%s start' % self.IPSEC_COMMAND)
190        chroot.add_startup_command('%s -c /%s -C /tmp/l2tpd.control' %
191                                   (self.XL2TPD_COMMAND,
192                                    self.XL2TPD_CONFIG_FILE))
193        self.preload_modules()
194        chroot.startup()
195
196
197    def stop_server(self):
198        """Start VPN server instance"""
199        chroot = self._chroot
200        chroot.run([self.IPSEC_COMMAND, 'stop'], ignore_status=True)
201        chroot.kill_pid_file(self.XL2TPD_PID_FILE, missing_ok=True)
202        chroot.kill_pid_file(self.PPPD_PID_FILE, missing_ok=True)
203        chroot.shutdown()
204
205
206    def get_log_contents(self):
207        """Return all logs related to the chroot."""
208        return self._chroot.get_log_contents()
209
210
211    def preload_modules(self):
212        """Pre-load ipsec modules since they can't be loaded from chroot."""
213        for module in self.PRELOAD_MODULES:
214            utils.system('modprobe %s' % module)
215
216
217class OpenVPNServer(VPNServer):
218    """Implementation of an OpenVPN service."""
219    PRELOAD_MODULES = ('tun',)
220    ROOT_DIRECTORIES = ('etc/openvpn', 'etc/ssl')
221    CA_CERTIFICATE_FILE = 'etc/openvpn/ca.crt'
222    SERVER_CERTIFICATE_FILE = 'etc/openvpn/server.crt'
223    SERVER_KEY_FILE = 'etc/openvpn/server.key'
224    DIFFIE_HELLMAN_FILE = 'etc/openvpn/diffie-hellman.pem'
225    OPENVPN_COMMAND = '/usr/sbin/openvpn'
226    OPENVPN_CONFIG_FILE = 'etc/openvpn/openvpn.conf'
227    OPENVPN_PID_FILE = 'run/openvpn.pid'
228    OPENVPN_STATUS_FILE = 'tmp/openvpn.status'
229    AUTHENTICATION_SCRIPT = 'etc/openvpn_authentication_script.sh'
230    EXPECTED_AUTHENTICATION_FILE = 'etc/openvpn_expected_authentication.txt'
231    PASSWORD = 'password'
232    USERNAME = 'username'
233    SERVER_IP_ADDRESS = '10.11.12.1'
234    CONFIGURATION = {
235        'etc/ssl/blacklist' : '',
236        CA_CERTIFICATE_FILE : site_eap_certs.ca_cert_1,
237        SERVER_CERTIFICATE_FILE : site_eap_certs.server_cert_1,
238        SERVER_KEY_FILE : site_eap_certs.server_private_key_1,
239        DIFFIE_HELLMAN_FILE : site_eap_certs.dh1024_pem_key_1,
240        AUTHENTICATION_SCRIPT :
241            '#!/bin/bash\n'
242            'diff -q $1 %(expected-authentication-file)s\n',
243        EXPECTED_AUTHENTICATION_FILE : '%(username)s\n%(password)s\n',
244        OPENVPN_CONFIG_FILE :
245            'ca /%(ca-cert)s\n'
246            'cert /%(server-cert)s\n'
247            'dev tun\n'
248            'dh /%(diffie-hellman-params-file)s\n'
249            'keepalive 10 120\n'
250            'local %(local-ip)s\n'
251            'log /var/log/openvpn.log\n'
252            'ifconfig-pool-persist /tmp/ipp.txt\n'
253            'key /%(server-key)s\n'
254            'persist-key\n'
255            'persist-tun\n'
256            'port 1194\n'
257            'proto udp\n'
258            'server 10.11.12.0 255.255.255.0\n'
259            'status /%(status-file)s\n'
260            'verb 5\n'
261            'writepid /%(pid-file)s\n'
262            '%(optional-user-verification)s\n'
263    }
264
265    def __init__(self, interface_name, address, network_prefix,
266                 perform_username_authentication=False):
267        self._chroot = network_chroot.NetworkChroot(interface_name,
268                                                    address, network_prefix)
269        self._perform_username_authentication = perform_username_authentication
270
271
272    def start_server(self):
273        """Start VPN server instance"""
274        chroot = self._chroot
275        chroot.add_root_directories(self.ROOT_DIRECTORIES)
276        # Create a configuration template from the key-value pairs.
277        chroot.add_config_templates(self.CONFIGURATION)
278        config_values = {
279            'ca-cert': self.CA_CERTIFICATE_FILE,
280            'diffie-hellman-params-file': self.DIFFIE_HELLMAN_FILE,
281            'expected-authentication-file': self.EXPECTED_AUTHENTICATION_FILE,
282            'optional-user-verification': '',
283            'password': self.PASSWORD,
284            'pid-file': self.OPENVPN_PID_FILE,
285            'server-cert': self.SERVER_CERTIFICATE_FILE,
286            'server-key': self.SERVER_KEY_FILE,
287            'status-file': self.OPENVPN_STATUS_FILE,
288            'username': self.USERNAME,
289        }
290        if self._perform_username_authentication:
291            config_values['optional-user-verification'] = (
292                    'auth-user-pass-verify /%s via-file\nscript-security 2' %
293                    self.AUTHENTICATION_SCRIPT)
294        chroot.add_config_values(config_values)
295        chroot.add_startup_command('chmod 755 %s' % self.AUTHENTICATION_SCRIPT)
296        chroot.add_startup_command('%s --config /%s &' %
297                                   (self.OPENVPN_COMMAND,
298                                    self.OPENVPN_CONFIG_FILE))
299        self.preload_modules()
300        chroot.startup()
301
302
303    def preload_modules(self):
304        """Pre-load modules since they can't be loaded from chroot."""
305        for module in self.PRELOAD_MODULES:
306            utils.system('modprobe %s' % module)
307
308
309    def get_log_contents(self):
310        """Return all logs related to the chroot."""
311        return self._chroot.get_log_contents()
312
313
314    def stop_server(self):
315        """Start VPN server instance"""
316        chroot = self._chroot
317        chroot.kill_pid_file(self.OPENVPN_PID_FILE, missing_ok=True)
318        chroot.shutdown()
319