]> git.llucax.com Git - software/pymin.git/blob - pymin/services/vpn/__init__.py
3b5046efbf5626cd1af7dccaf64a9d0ab936fd4d
[software/pymin.git] / pymin / services / vpn / __init__.py
1 # vim: set encoding=utf-8 et sw=4 sts=4 :
2
3 import os
4 import signal
5 from os import path
6 import logging ; log = logging.getLogger('pymin.services.vpn')
7
8
9 from pymin.seqtools import Sequence
10 from pymin.dispatcher import Handler, handler, HandlerError
11 from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \
12                                 TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError
13
14
15 class Host(Sequence):
16     def __init__(self, vpn_src, ip, vpn_src_net, key):
17         self.name = vpn_src
18         self.ip = ip
19         self.src_net = vpn_src_net
20         self.pub_key = key
21         self.dele = False
22
23     def as_tuple(self):
24         return(self.name, self.ip, self.src_net, self.pub_key)
25
26 class HostHandler(DictComposedSubHandler):
27
28     handler_help = u"Manage hosts for a vpn"
29     _comp_subhandler_cont = 'vpns'
30     _comp_subhandler_attr = 'hosts'
31     _comp_subhandler_class = Host
32
33     @handler('usage: add <vpn_src> <ip> <vpn_src_net> <key>')
34     def delete(self, vpn_src, host):
35         DictComposedSubHandler.delete(self, vpn_src, host)
36         if vpn_src in parent.vpns:
37             if host in parent.vpns[vpn_src].hosts:
38                 parent.vpns[vpn_src].hosts[host].dele = True
39
40
41 class Vpn(Sequence):
42     def __init__(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask, pub_key, priv_key):
43         self.vpn_src = vpn_src
44         self.vpn_dst = vpn_dst
45         self.vpn_src_ip = vpn_src_ip
46         self.vpn_src_mask = vpn_src_mask
47         self.pub_key = pub_key
48         self.priv_key = priv_key
49         self.hosts = dict()
50         self.dele = False
51
52     def as_tuple(self):
53         return(self.vpn_src, self.vpn_dst, self.vpn_src_ip, self.vpn_src_mask, self.pub_key, self.priv_key)
54
55     def update(self, vpn_dst=None, vpn_src_ip=None, vpn_src_mask=None):
56         if vpn_dst is not None:
57             self.vpn_dst = vpn_dst
58         if vpn_src_ip is not None:
59             self.vpn_src_ip = vpn_src_ip
60         if vpn_src_mask is not None:
61             self.vpn_src_mask = vpn_src_mask
62
63
64 class VpnHandler(Restorable, ConfigWriter,
65                    TransactionalHandler, DictSubHandler):
66
67     handler_help = u"Manage vpn service"
68
69     _cont_subhandler_attr = 'vpns'
70     _cont_subhandler_class = Vpn
71
72     _persistent_attrs = ('vpns','hosts')
73
74     _restorable_defaults = dict(
75             vpns = dict(),
76             hosts = dict(),
77     )
78
79     _config_writer_files = ('tinc.conf','tinc-up','host')
80     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
81
82     def __init__(self,  pickle_dir='.', config_dir='/etc/tinc'):
83         log.debug(u'VpnHandler(%r, %r)', pickle_dir, config_dir)
84         DictSubHandler.__init__(self, self)
85         self._config_writer_cfg_dir = config_dir
86         self._persistent_dir = pickle_dir
87         self._config_build_templates()
88         self._restore()
89         self.host = HostHandler(self)
90
91     @handler('usage : add <vpn_name> <vpn_dst> <vpn_src_ip> <vpn_src_mask>')
92     def add(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask):
93         log.debug(u'VpnHandler.add(%r, %r, %r, %r)', vpn_src, vpn_dst,
94                     vpn_src_ip, vpn_src_mask)
95         if vpn_src in self.vpns:
96             if self.vpns[vpn_src].dele:
97                 log.debug(u'VpnHandler.add: deleted, undeleting')
98                 self.vpns[vpn_src] = False
99         else:
100             DictSubHandler.add(self, vpn_src, vpn_dst, vpn_src_ip,
101                                 vpn_src_mask, None, None)
102
103     @handler('usage : delete <vpn_name>')
104     def delete(self, vpn_src):
105         log.debug(u'VpnHandler.delete(%r)', vpn_src)
106         if vpn_src in self.vpns:
107             self.vpns[vpn_src].dele = True;
108
109
110     @handler('usage: start <vpn_name>')
111     def start(self, vpn_src):
112         log.debug(u'VpnHandler.start(%r)', vpn_src)
113         if vpn_src in self.vpns:
114             call(('tincd','--net='+ vpn_src))
115
116     @handler('usage: stop <vpn_name>')
117     def stop(self, vpn_src):
118         log.debug(u'VpnHandler.stop(%r)', vpn_src)
119         if vpn_src in self.vpns:
120             pid_file = '/var/run/tinc.' + vpn_src + '.pid'
121             log.debug(u'VpnHandler.stop: getting pid from %r', pid_file)
122             if path.exists(pid_file):
123                 pid = file(pid_file).readline()
124                 pid = int(pid.strip())
125                 try:
126                     log.debug(u'VpnHandler.stop: killing pid %r', pid)
127                     os.kill(pid, signal.SIGTERM)
128                 except OSError:
129                     log.debug(u'VpnHandler.stop: error killing: %r', e)
130             else:
131                 log.debug(u'VpnHandler.stop: pid file not found')
132
133     def _write_config(self):
134         log.debug(u'VpnHandler._write_config()')
135         for v in self.vpns.values():
136             log.debug(u'VpnHandler._write_config: processing %r', v)
137             #chek whether it's been created or not.
138             if not v.dele:
139                 if v.pub_key is None:
140                     log.debug(u'VpnHandler._write_config: new VPN, generating '
141                                 'key...')
142                     try:
143                         log.debug(u'VpnHandler._write_config: creating dir %r',
144                                     path.join(self._config_writer_cfg_dir,
145                                                 v.vpn_src ,'hosts'))
146                         #first create the directory for the vpn
147                         call(('mkdir', '-p', path.join(
148                                             self._config_writer_cfg_dir,
149                                             v.vpn_src, 'hosts')))
150                         #this command should generate 2 files inside the vpn
151                         #dir, one rsa_key.priv and one rsa_key.pub
152                         #for some reason debian does not work like this
153                         # FIXME if the < /dev/null works, is magic!
154                         log.debug(u'VpnHandler._write_config: creating key...')
155                         call(('tincd', '-n', v.vpn_src, '-K', '<', '/dev/null'))
156                         #open the created files and load the keys
157                         f = file(path.join(self._config_writer_cfg_dir,
158                                             v.vpn_src, 'rsa_key.priv'), 'r')
159                         priv = f.read()
160                         f.close()
161                         f = file(path.join(self._config_writer_cfg_dir,
162                                             v.vpn_src, 'rsa_key.pub'), 'r')
163                         pub = f.read()
164                         f.close()
165                         v.pub_key = pub
166                         v.priv_key = priv
167                     except ExecutionError, e:
168                         log.debug(u'VpnHandler._write_config: error executing '
169                                     'the command: %r', e)
170
171                 vars = dict(
172                     vpn = v,
173                 )
174                 self._write_single_config('tinc.conf',
175                                 path.join(v.vpn_src, 'tinc.conf'), vars)
176                 self._write_single_config('tinc-up',
177                                 path.join(v.vpn_src, 'tinc-up'), vars)
178                 for h in v.hosts.values():
179                     if not h.dele:
180                         vars = dict(
181                             host = h,
182                         )
183                         self._write_single_config('host',
184                                 path.join(v.vpn_src, 'hosts', h.name), vars)
185                     else:
186                         log.debug(u'VpnHandler._write_config: removing...')
187                         try:
188                             # FIXME use os.unlink()
189                             call(('rm','-f',
190                                     path.join(v.vpn_src, 'hosts', h.name)))
191                             del v.hosts[h.name]
192                         except ExecutionError, e:
193                             log.debug(u'VpnHandler._write_config: error '
194                                     'removing files: %r', e)
195             else:
196                 #delete the vpn root at tinc dir
197                 if path.exists('/etc/tinc/' + v.vpn_src):
198                     self.stop(v.vpn_src)
199                     call(('rm','-rf','/etc/tinc/' + v.vpn_src))
200                     del self.vpns[v.vpn_src]
201
202
203 if __name__ == '__main__':
204
205     logging.basicConfig(
206         level   = logging.DEBUG,
207         format  = '%(asctime)s %(levelname)-8s %(message)s',
208         datefmt = '%H:%M:%S',
209     )
210
211     v = VpnHandler()
212     v.add('prueba','sarasa','192.168.0.188','255.255.255.0')
213     v.host.add('prueba', 'azazel' ,'192.168.0.77', '192.168.0.0',
214                 'kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb')
215     v.commit()
216