source: n4d-freeradius/trunk/fuentes/install/usr/share/n4d/python-plugins/FreeRadiusManager.py

Last change on this file was 5686, checked in by hectorgh, 2 years ago

updating plugin

File size: 10.2 KB
Line 
1#!/usr/bin/env python
2
3import os
4import shutil
5import re
6import tempfile
7import copy
8
9import xmlrpclib as x
10
11from jinja2 import Environment
12from jinja2.loaders import FileSystemLoader
13
14
15
16class FreeRadiusManager:
17       
18       
19        def __init__(self):
20               
21                self.radius_path="/etc/freeradius/"
22                self.templates_path="/usr/share/n4d/templates/n4d-freeradius/"
23                self.groups_file=self.radius_path + "users.lliurex_groups"
24               
25                self.groups={}
26                self.diversions={}
27               
28                self.variable_list=["LDAP_BASE_DN","INTERNAL_NETWORK","INTERNAL_MASK"]
29               
30                self.diversions["/etc/freeradius/clients.conf"]="/etc/freeradius/clients.conf.diverted"
31                self.diversions["/etc/freeradius/eap.conf"]="/etc/freeradius/eap.conf.diverted"
32                self.diversions["/etc/freeradius/users"]="/etc/freeradius/users.diverted"
33                self.diversions["/etc/freeradius/radiusd.conf"]="/etc/freeradius/radiusd.conf.diverted"
34               
35                self.diversions["/etc/freeradius/modules/ldap"]="/etc/freeradius/modules/ldap.diverted"
36                self.diversions["/etc/freeradius/modules/mschap"]="/etc/freeradius/modules/mschap.diverted"
37               
38                self.diversions["/etc/freeradius/sites-available/default"]="/etc/freeradius/sites-available/default.diverted"
39                self.diversions["/etc/freeradius/sites-available/inner-tunnel"]="/etc/freeradius/sites-available/inner-tunnel.diverted"
40               
41               
42        #def init
43       
44        def startup(self,options):
45       
46                self.variable=copy.deepcopy(objects["VariablesManager"].get_variable("FREERADIUS"))
47               
48                if self.variable==None:
49                       
50                        self.variable={}
51                        self.variable["configured"]=False
52                        self.variable["groups_filter"]={}
53                        self.variable["groups_filter"]["enabled"]=False
54                        self.variable["groups_filter"]["groups"]={}
55                        self.variable["groups_filter"]["default_auth"]=None
56                       
57                        try:
58                                objects["VariablesManager"].add_variable("FREERADIUS",copy.deepcopy(self.variable),"","Freeradius service variable","n4d-freeradius")
59                        except:
60                                # If this fails, something is horribly wrong and we have bigger problems than this variable not being saved
61                                # Hopefully we'll be able to do it later, anyway
62                                pass
63
64                if self.variable["groups_filter"]["enabled"]:
65                        groups=self.parse_groups_file()
66                        if groups != self.variable["groups_filter"]["groups"]:
67                                self.variable["groups_filter"]["groups"]=groups
68                                self.save_variable()
69               
70        #def startup
71
72        def is_configured(self):
73
74                return self.variable["configured"]
75
76        #def is_configured
77
78
79        def parse_groups_file(self):
80               
81                group_pattern='^DEFAULT\s+Ldap-Group\s*==\s*"(\w+)"\s*(,\s*Auth-Type\s*:=\s*\w+\s*)?$'
82                groups={}
83               
84                if os.path.exists(self.groups_file):
85                       
86                        f=open(self.groups_file)
87                        for line in f.readlines():
88                                ret=re.match(group_pattern,line)
89                                if ret!=None:
90                                        group,auth_type=ret.groups()
91                                        groups[group]=auth_type
92                                       
93                        f.close()
94               
95                return groups
96               
97        #def parse_groups_file
98
99
100        def get_allowed_groups(self):
101
102                groups=self.parse_groups_file()
103                if len(groups) < 1:
104                        groups=self.variable["groups_filter"]["groups"]
105                return {"status":True,"msg":groups.keys()}
106
107        #def get_allowed_groups
108       
109       
110        def generate_groups_file(self,groups=None):
111               
112                header = "# FILE GENERATED BY n4d-freeradius PLUGIN\n\n"
113                final_rule="DEFAULT Auth-Type := Reject\n\n"
114               
115                group_skel='DEFAULT Ldap-Group == "%s"'
116                extra_auth=", Auth-Type := EAP"
117                               
118                if not groups:
119                        groups=self.variable["groups_filter"]["groups"]
120                       
121                fd,tmpfile=tempfile.mkstemp()
122                f=open(tmpfile,"w")
123                f.write(header)
124                for group in groups:
125                        f.write(group_skel%group)
126                        if groups[group]!=None:
127                                f.write(extra_auth)
128                        f.write("\n")
129       
130                f.write("\n")           
131                f.write(final_rule)
132                f.close()
133                os.close(fd)
134               
135                shutil.copy(tmpfile,self.groups_file)
136                self.fix_perms(self.radius_path+"users.lliurex_groups")
137               
138                return True
139               
140        #def generate_groups_file
141       
142       
143        def clean_groups_file(self):
144               
145                f=open(self.groups_file,"w")
146                f.write("# FILE GENERATED BY n4d-freeradius PLUGIN\n\n")
147                f.close()
148               
149        #def clean_groups_file
150       
151       
152        def set_filter_default_auth(self,auth_type=None):
153               
154                if not self.variable["groups_filter"]["enabled"]:
155                        return {"msg":False,"status":"Filter not enabled"}
156               
157                self.variable["groups_filter"]["default_auth"]=auth_type
158               
159                for group in self.variable["groups_filter"]["groups"]:
160                        self.variable["groups_filter"]["groups"][group]=auth_type
161                               
162                self.generate_groups_file()
163                self.restart_service()
164               
165                self.save_variable()
166               
167                return {"status":True,"msg":"auth configured"}
168               
169        #def set_filter_default_auth
170       
171       
172        def add_group_to_filter(self,group,extra_auth=None):
173               
174                if not self.variable["groups_filter"]["enabled"]:
175                        return {"status":False,"msg":"Filter not enabled"}
176                       
177                if extra_auth==None:
178                        extra_auth=self.variable["groups_filter"]["default_auth"]
179               
180                groups=self.parse_groups_file()
181               
182                if group not in groups or groups[group]!=extra_auth:
183                        self.variable["groups_filter"]["groups"][group]=extra_auth
184                       
185                self.generate_groups_file()
186                self.save_variable()
187                self.restart_service()
188               
189                return {"status":True,"msg":"Group added"}
190               
191               
192        #def add_group_to_filter
193       
194       
195        def remove_group_from_filter(self,group):
196               
197                if not self.variable["groups_filter"]["enabled"]:
198                        return {"status":False,"msg":"Filter not enabled"}
199               
200                groups=self.parse_groups_file()
201               
202                if group in groups:
203                        groups.pop(group)
204                        self.variable["groups_filter"]["groups"]=groups
205                       
206                self.generate_groups_file()
207                self.restart_service()
208                self.save_variable()
209               
210                return {"status":True, "msg": "Group removed"}
211               
212        #def remove_group_from_filter
213       
214       
215        def enable_group_filtering(self):
216               
217                self.variable["groups_filter"]["enabled"]=True
218                self.generate_groups_file()
219               
220                self.save_variable()
221                self.restart_service()
222               
223                return {"status":True,"msg":""}
224               
225        #def enable_filtering
226       
227       
228        def disable_group_filtering(self):
229               
230                # get groups currently written in case user did it manually
231                groups=self.parse_groups_file()
232                # save groups in local variable only if it has content
233                # rely on variable groups value if it doesn't
234                if len(groups)>0:
235                        self.variable["groups_filter"]["groups"]=groups
236               
237                self.clean_groups_file()
238                self.variable["groups_filter"]["enabled"]=False
239               
240                self.save_variable()
241                self.restart_service()
242               
243                return {"status":True,"msg":""}
244               
245        #def empty_groups_file
246       
247       
248        def save_variable(self):
249               
250                objects["VariablesManager"].set_variable("FREERADIUS",copy.deepcopy(self.variable))
251               
252        #def save_variable
253       
254        def restart_service(self):
255               
256                os.system("systemctl restart freeradius")
257               
258        #def restart_service
259               
260       
261        def render_templates(self,server,radius_secret,ldap_user,ldap_pwd,router_ip):
262               
263       
264                vars=objects["VariablesManager"].get_variable_list(self.variable_list)
265               
266                vars["RADIUS_SECRET"]=radius_secret
267                vars["LDAP_USER"]=ldap_user
268                vars["LDAP_PASSWORD"]=ldap_pwd
269                vars["SERVER"]=server
270                vars["ROUTER_IP"]=router_ip
271               
272                env = Environment(loader=FileSystemLoader(self.templates_path))
273
274                template=env.get_template("clients.conf")
275                str_template=template.render(vars).encode("utf-8")
276                clients_str=str_template
277               
278                f=open(self.templates_path+"modules/ldap")
279                lines=f.readlines()
280                f.close()
281                 
282                str_template=""
283               
284                for line in lines:
285                       
286                        if "%%LDAP_USER%%" in line:
287                                line=line.replace("%%LDAP_USER%%",vars["LDAP_USER"])
288
289                        if "%%LDAP_PASSWORD%%" in line:
290                                line=line.replace("%%LDAP_PASSWORD%%",vars["LDAP_PASSWORD"])
291
292                        if "%%LDAP_BASE_DN%%" in line:
293                                line=line.replace("%%LDAP_BASE_DN%%",vars["LDAP_BASE_DN"])
294
295                        if "%%SERVER%%" in line:
296                                line=line.replace("%%SERVER%%",vars["SERVER"])
297                               
298                        str_template+=line
299
300               
301                ldap_str=str_template
302               
303                return (clients_str,ldap_str)
304       
305        #def render_template
306
307       
308        def install_conf_files(self,server,radius_secret,ldap_user,ldap_pwd,router_ip):
309               
310                try:
311               
312                        clients_str,ldap_str=self.render_templates(server,radius_secret,ldap_user,ldap_pwd,router_ip)
313                       
314                        if not os.path.exists(self.radius_path):
315                                os.makedirs(self.radius_path)
316                       
317                        # clients.conf
318                       
319                        f=open(self.radius_path+"clients.conf.lliurex","w")
320                        f.write(clients_str)
321                        f.close()
322                       
323                        self.fix_perms(self.radius_path+"clients.conf.lliurex")
324                       
325                       
326                        # modules/ldap
327                       
328                        if not os.path.exists(self.radius_path+"modules"):
329                                os.makedirs(self.radius_path+"modules")
330                       
331                        f=open(self.radius_path+"modules/ldap","w")
332                        f.write(ldap_str)
333                        f.close()
334                       
335                        # default
336                        if not os.path.exists(self.radius_path+"sites-available"):
337                                os.makedirs(self.radius_path+"sites-available")
338                       
339                        shutil.copy(self.templates_path+"sites-available/default",self.radius_path+"sites-available/default.lliurex")
340                       
341                        # inner-tunnel
342                        shutil.copy(self.templates_path+"sites-available/inner-tunnel",self.radius_path+"sites-available/inner-tunnel.lliurex")
343                       
344                        # radiusd.conf
345                        shutil.copy(self.templates_path+"radiusd.conf",self.radius_path+"radiusd.conf.lliurex")
346                        self.fix_perms(self.radius_path+"radiusd.conf.lliurex")
347                       
348                        # eap.conf
349                        shutil.copy(self.templates_path+"eap.conf",self.radius_path+"eap.conf.lliurex")
350                        self.fix_perms(self.radius_path+"eap.conf.lliurex")
351                       
352                        # users.conf
353                        shutil.copy(self.templates_path+"users",self.radius_path+"users.lliurex")
354                       
355                        # user.lliurex_groups
356                        shutil.copy(self.templates_path+"users.lliurex_groups",self.radius_path)
357                        self.fix_perms(self.radius_path+"users.lliurex_groups")
358                       
359                        # modules/mschap
360                        shutil.copy(self.templates_path+"modules/mschap",self.radius_path+"modules/mschap.lliurex")
361
362                       
363                        self.enable_diversions()               
364       
365                        os.system("systemctl restart freeradius")
366                       
367                        self.variable["groups_filter"]["enabled"]=False
368                        self.variable["configured"]=True
369                       
370                        self.save_variable()
371                       
372                        return {"status":True,"msg":str(True)}
373                       
374                except Exception as e:
375                       
376                        return {"status":False,"msg":str(e)}
377                       
378               
379        #def install_conf_files
380       
381       
382        def fix_perms(self,f):
383               
384                os.system("chown root:freerad %s"%f)
385                os.system("chmod 640 %s"%f)             
386               
387        #def fix_perms
388       
389
390        def enable_diversions(self):
391
392                for original_file in self.diversions:
393
394                        lliurex_file=original_file+".lliurex"
395                       
396                        if not os.path.exists(self.diversions[original_file]):
397                                command="dpkg-divert --add --package n4d-freeradius --rename --divert '%s' '%s'"%(self.diversions[original_file],original_file)
398                                os.system(command)
399                               
400                        if not os.path.islink(original_file):
401                                os.symlink(lliurex_file, original_file)
402
403        #def enable_diversions
404
405
406        def disable_diversions(self):
407
408                pass
409
410        #def disable_diversions
411       
412       
413
414
415       
416#class RadiusManager
417
418if __name__=="__main__":
419       
420        r=RadiusManager()
421        r.install_conf_files("server","myradius1","cn=roadmin...","2","")
Note: See TracBrowser for help on using the repository browser.