Home | History | Annotate | Download | only in cros
      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 
      5 import logging
      6 
      7 from autotest_lib.client.bin import utils
      8 from autotest_lib.client.cros import network_chroot
      9 from autotest_lib.client.common_lib.cros import site_eap_certs
     10 
     11 class 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 
     24 class 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 
    217 class 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