summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/vpn/service.py
blob: e56546ea0bcd07bcd04a4857fc1491e708c64b20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# service.py
# Copyright (C) 2015-2017 LEAP
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
VPN service declaration.
"""

import os

from twisted.internet import defer

from leap.bitmask.hooks import HookableService
from leap.bitmask.vpn.vpn import VPNManager
from leap.bitmask.vpn._checks import is_service_ready, get_vpn_cert_path
from leap.bitmask.vpn._config import get_bitmask_helper_path
from leap.bitmask.vpn._config import get_bitmask_polkit_policy_path
from leap.bitmask.vpn import privilege
from leap.common.config import get_path_prefix
from leap.common.files import check_and_fix_urw_only


class VPNService(HookableService):

    name = 'vpn'

    def __init__(self, basepath=None):
        """
        Initialize VPN service
        """
        super(VPNService, self).__init__()

        self._started = False
        self._vpn = None
        self._domain = ''

        if basepath is None:
            self._basepath = get_path_prefix()
        else:
            self._basepath = basepath

    def startService(self):
        print "Starting VPN Service..."
        # TODO this could trigger a check for validity of the certificates,
        # etc.
        super(VPNService, self).startService()

    def stopService(self):
        print "Stopping VPN Service..."
        super(VPNService, self).stopService()

    def start_vpn(self, domain):
        # TODO check if the VPN is started and return an error if it is.
        self._setup(domain)
        self._vpn.start()
        self._started = True
        self._domain = domain
        return {'result': 'started'}

    def stop_vpn(self):
        # TODO -----------------------------
        # when shutting down the main bitmaskd daemon, this should be called.

        if self._started:
            self._vpn.stop()
            self._started = False
            return {'result': 'stopped'}

    def do_status(self):
        if self._vpn:
            status = self._vpn.get_status()
        else:
            status = {'VPN': 'OFF'}
        status['domain'] = self._domain
        return status

    def do_check(self):
        """Check whether the VPN Service is properly configured,
        and can be started"""
        # TODO either pass a provider, or set a given provider
        _ready = is_service_ready('demo.bitmask.net')
        if _ready:
            result = 'ok'
        else:
            result = 'no'
        return {'vpn_ready': result}

    @defer.inlineCallbacks
    def do_get_cert(self, provider):
        # fetch vpn cert and store
        bonafide = self.parent.getServiceNamed("bonafide")
        _, cert_str = yield bonafide.do_get_vpn_cert()

        cert_path = get_vpn_cert_path(provider)
        cert_dir = os.path.dirname(cert_path)
        if not os.path.exists(cert_dir):
            os.makedirs(cert_dir, mode=0700)
        with open(cert_path, 'w') as outf:
            outf.write(cert_str)
        check_and_fix_urw_only(cert_path)
        defer.returnValue({'get_cert': 'ok'})

    def do_install(self):
        ask = privilege.install_helpers()
        return {'install': 'ok'}

    def do_uninstall(self):
        ask = privilege.uninstall_helpers()
        return {'uninstall': 'ok'}

    def _setup(self, provider):
        """Set up VPNManager for a specified provider.

        :param provider: the provider to use, e.g. 'demo.bitmask.net'
        :type provider: str"""

        # FIXME ---------------------------------------------------------
        # XXX picked manually from eip-service.json
        remotes = (
            ("198.252.153.84", "1194"),
            ("46.165.242.169", "1194"),
        )

        prefix = os.path.join(self._basepath,
                              "leap/providers/{0}/keys".format(provider))
        cert_path = key_path = prefix + "/client/openvpn.pem"
        ca_path = prefix + "/ca/cacert.pem"

        # FIXME
        # XXX picked manually from vpn-service.json
        extra_flags = {
            "auth": "SHA1",
            "cipher": "AES-128-CBC",
            "keepalive": "10 30",
            "tls-cipher": "DHE-RSA-AES128-SHA",
        }

        self._vpn = VPNManager(remotes, cert_path, key_path, ca_path,
                               extra_flags)