source: n4d-samba/trunk/fuentes/install/usr/share/n4d/python-plugins/SambaManager.py @ 844

Last change on this file since 844 was 844, checked in by hectorgh, 4 years ago

stop relying on golem to create roadming password

File size: 14.8 KB
Line 
1import ldap 
2import ldap.sasl 
3import ldap.modlist
4import ast
5import datetime
6import smbpasswd
7import grp
8import tempfile
9import shutil
10import os
11import os.path
12import pwd
13import spwd
14import time
15import tarfile
16import random
17import string
18
19from jinja2 import Environment
20from jinja2.loaders import FileSystemLoader
21
22class SambaManager:
23        predepends = ['VariablesManager','SlapdManager']
24        def __init__(self):
25                # Vars
26               
27                self.LDAP_SECRET1 = '/etc/lliurex-cap-secrets/ldap-master/ldap'
28                self.LDAP_SECRET2 = '/etc/lliurex-secrets/passgen/ldap.secret'
29                self.log_path = '/var/log/n4d/samba'
30                self.tpl_env = Environment(loader=FileSystemLoader('/usr/share/n4d/templates/samba'))
31                self.available_acl_path = '/usr/share/n4d-ldap/available_acl/samba/'
32                self.enable_acl_path = '/var/lib/n4d-ldap/enable_acl/'
33        #def __init__
34
35        def apt(self):
36                pass
37        #def apt
38        def startup(self,options):
39                objects["VariablesManager"].init_variable('SAMBASID')
40                self.connection_ldap()
41
42        #def startup
43       
44        def test(self):
45                pass
46        #def test
47       
48        def backup(self,folder_path='/backup/'):
49                try:
50                        if not folder_path.endswith("/"):
51                                folder_path+="/"
52                        file_path=folder_path+get_backup_name("Samba")
53                        tar=tarfile.open(file_path,"w:gz")
54                        tar.add('/etc/samba')
55                        tar.add('/etc/lliurex-secrets/passgen/ldap.secret')
56                        tar.add('/var/lib/lliurex-folders')
57                        tar.close()
58                        return [True,file_path]
59                       
60                except Exception as e:
61                        return [False,str(e)]
62        #def backup
63       
64        def restore(self,file_path=None):
65                if file_path==None:
66                        for f in sorted(os.listdir("/backup"),reverse=True):
67                                if "Samba" in f:
68                                        file_path="/backup/"+f
69                                        break
70
71                try:
72
73                        if os.path.exists(file_path):
74                               
75                                tmp_dir=tempfile.mkdtemp()
76                                tar=tarfile.open(file_path)
77                                tar.extractall(tmp_dir)
78                                tar.close()
79                                copy_folder = os.path.join(tmp_dir,'*')
80                                os.system('rsync -ax ' + copy_folder + ' /')
81                                os.system('chmod 600 /etc/lliurex-secrets/passgen/ldap.secret')
82                                os.system('smbpasswd -w $(cat /etc/lliurex-secrets/passgen/ldap.secret)')
83                                return [True,""]
84                               
85                except Exception as e:
86                               
87                        return [False,str(e)]
88        #def restore
89
90        def update_xid_counter(self,ou,new_value):
91                if not self.test_ldap_connection():
92                        if not self.connection_ldap():
93                                return {"status":False,"msg":"Connection with ldap is not created"}
94               
95                list_entry = self.connect_ldap.search_s(ou,ldap.SCOPE_SUBTREE)
96                if len(list_entry) > 0 :
97                        name_entry,entry = list_entry[0]
98                        if entry.has_key('x-lliurex-xid-counter'):
99                                if len(entry['x-lliurex-xid-counter']) > 0 and int(entry['x-lliurex-xid-counter'][0]) < int(new_value):
100                                        aux_entry = entry.copy()
101                                        aux_entry['x-lliurex-xid-counter'] = [str(new_value)]
102                                        mod_entry = ldap.modlist.modifyModlist(entry,aux_entry)
103                                        try:
104                                                self.connect_ldap.modify_s(name_entry,mod_entry)
105                                        except Exception as e:
106                                                return [False,str(e.message)]
107                                return [True,""]
108                        else:
109                                return [False,"ou " + ou + " hasn't x-lliurex-xid-counter property"]
110                else:
111                        return [False,"ou " + ou + " not exist"]
112        #def update_xid_counter
113
114        def load_schema(self):
115                template = self.tpl_env.get_template('schemas')
116                string_template = template.render().encode('utf-8')
117                aux_dic = ast.literal_eval(string_template)
118                for entry_name in aux_dic.keys():
119                        if not objects.has_key('SlapdManager'):
120                                return {'status':False,'msg':'This function depend on SlapdManager, but this is not installed or not working'}
121                        result = objects['SlapdManager'].load_schema(entry_name,aux_dic[entry_name],True)
122                        if not result['status']:
123                                return result
124                return {'status':True,'msg':'Load schema to samba'}
125        #def load_schema
126       
127        def load_index(self):
128                template = self.tpl_env.get_template('index')
129                string_template = template.render().encode('utf-8')
130                aux_dic = ast.literal_eval(string_template)
131                if not objects.has_key('SlapdManager'):
132                        return {'status':False,'msg':'This function depend on SlapdManager, but this is not installed or not working'}
133                result = objects['SlapdManager'].update_index(aux_dic)
134                if not result['status']:
135                        return result
136                return {'status':True,'msg':'Load index to samba'}
137        #def load_index
138       
139        def load_basic_structure(self):
140                template = self.tpl_env.get_template('basic-structure')
141                if  objects.has_key("VariablesManager"):
142                        environment_basic = objects["VariablesManager"].get_variable_list(['SAMBA_DOMAIN_NAME','LDAP_BASE_DN','SAMBASID'])
143                string_template = template.render(environment_basic).encode('utf-8')
144                aux_dic = ast.literal_eval(string_template)
145                if not objects.has_key('SlapdManager'):
146                        return {'status':False,'msg':'This function depend on SlapdManager, but this is not installed or not working'}
147                result = objects['SlapdManager'].insert_dictionary(aux_dic,i_existing=True)
148                if result['status']:
149                        return {'status':True,'msg':'Load basic structure to work samba'}
150                else:
151                        return result
152        #def load_basic_structure
153       
154        def load_all_system_groups(self,min_gid=None,max_gid=1000):
155                template = self.tpl_env.get_template('system-group')
156                if  objects.has_key("VariablesManager"):
157                        environment_vars = objects["VariablesManager"].get_variable_list(['LDAP_BASE_DN'])
158                max_counter = 0
159                for x in grp.getgrall():
160                        environment_vars["GROUP_NAME"] = x.gr_name
161                        environment_vars["GROUP_ID"] = x.gr_gid
162                        if x.gr_gid <= min_gid or x.gr_gid >= max_gid:
163                                continue
164                        if int(x.gr_gid) > max_counter:
165                                max_counter = x.gr_gid
166                        string_template = template.render(environment_vars).encode('utf-8')
167                        aux_dic = ast.literal_eval(string_template)
168                        if not objects.has_key('SlapdManager'):
169                                return {'status':False,'msg':'This function depend on SlapdManager, but this is not installed or not working'}
170                        result = objects['SlapdManager'].insert_dictionary(aux_dic,i_existing=True)
171                        if not result['status']:
172                                return result
173                result = self.update_xid_counter("ou=System,ou=Groups,"+environment_vars['LDAP_BASE_DN'],max_counter)
174                if result[0]:
175                        return {'status':True,'msg':'Load all groups from system'}
176                else:
177                        return {'status':False,'msg':result[1]}
178        #def load_all_system_groups
179
180        def load_admin_system_user(self):
181                template = self.tpl_env.get_template('admin-users')
182                if  objects.has_key("VariablesManager"):
183                        environment_vars = objects["VariablesManager"].get_variable_list(['LDAP_BASE_DN','SAMBASID'])
184                users_adm = grp.getgrnam('adm').gr_mem
185                max_uid = 0
186                for x in users_adm:
187                        user = pwd.getpwnam(x)
188                        environment_vars['USERNAME'] = user.pw_name
189                        environment_vars['USERNAME_UID'] = user.pw_uid
190                        if int(user.pw_uid) > max_uid:
191                                max_uid = int(user.pw_uid)
192                        environment_vars['USERHOME'] = user.pw_dir
193                        environment_vars['USERPASSWORD'] = "{crypt}" + spwd.getspnam(user.pw_name).sp_pwd
194                        environment_vars['SAMBASIDUSER'] = str(environment_vars['SAMBASID']) + "-" + str(environment_vars['USERNAME_UID'])
195                        string_template = template.render(environment_vars).encode('utf-8')
196                        aux_dic = ast.literal_eval(string_template)
197                       
198                        if not objects.has_key('SlapdManager'):
199                                return {'status':False,'msg':'This function depend on SlapdManager, but this is not installed or not working'}
200                        result = objects['SlapdManager'].insert_dictionary(aux_dic,i_existing=True)
201                        if not result['status']:
202                                return result
203                        aux_dn = aux_dic.keys()[0]
204                        result = self.insert_to_admin_profile(aux_dn,aux_dic[aux_dn]['uid'])
205                        if not result['status']:
206                                return result
207                result = self.update_xid_counter("ou=Admins,ou=People,"+environment_vars['LDAP_BASE_DN'],max_uid)
208                if result[0]:
209                        return {'status':True,'msg':'Load all admin users from system'}
210                else:
211                        return {'status':False,'msg':result[1]}
212        #def load_admin_system_user
213       
214        def load_net_admin_user(self,password=None):
215                template = self.tpl_env.get_template('net-admin-user')
216                if  objects.has_key("VariablesManager"):
217                        if not objects.has_key('SlapdManager'):
218                                return {'status':False,'msg':'This function depend on SlapdManager, but this is not installed or not working'}
219                        environment_vars = objects["VariablesManager"].get_variable_list(['LDAP_BASE_DN','SAMBASID'])
220                        environment_vars['USERPASSWORD'] = objects['SlapdManager'].generate_ssha_password(password).strip()
221                        environment_vars["NTPASSWORD"]=smbpasswd.nthash(password)
222                        environment_vars["LMPASSWORD"]=smbpasswd.lmhash(password)
223                        environment_vars["LASTSET"]=str(int(time.time()))
224                        string_template = template.render(environment_vars).encode('utf-8')
225                        aux_dic = ast.literal_eval(string_template)
226                        result = objects['SlapdManager'].insert_dictionary(aux_dic,i_existing=True)
227                        if not result['status']:
228                                return result
229                        aux_dn = aux_dic.keys()[0]
230                        result = self.insert_to_admin_profile(aux_dn,aux_dic[aux_dn]['uid'])
231                        if not result['status']:
232                                return result
233                        result = self.insert_to_admin_groups(aux_dic[aux_dn]['uid'])
234                        if not result['status']:
235                                return result
236                        result = self.update_xid_counter("ou=Admins,ou=People,"+environment_vars['LDAP_BASE_DN'],1042)
237                        if result[0]:
238                                return {'status':True,'msg':'Load all admin users from system'}
239                        else:
240                                return {'status':False,'msg':result[1]}
241                else:
242                        return {'status':False,'msg':'Variables Manager n4d plugin not working'}
243                       
244        def load_ro_admin_user(self):
245               
246                template=self.tpl_env.get_template("ro-admin-user")
247               
248                environment_vars=objects["VariablesManager"].get_variable_list(["LDAP_BASE_DN"])
249                password="".join(random.sample(string.letters+string.digits, 4))
250                environment_vars["PASSWORD"]=objects['SlapdManager'].generate_ssha_password(password).strip()
251                string_template=template.render(environment_vars).encode("utf-8")
252                aux_dic=ast.literal_eval(string_template)
253                result=objects["SlapdManager"].insert_dictionary(aux_dic,i_existing=True)
254               
255                return result
256               
257               
258        #def load_ro_admin_user
259       
260        def load_education(self):
261                template = self.tpl_env.get_template('education')
262                if  objects.has_key("VariablesManager"):
263                        environment_vars = objects["VariablesManager"].get_variable_list(['LDAP_BASE_DN','SAMBASID'])
264                string_template = template.render(environment_vars).encode('utf-8')
265                aux_dic = ast.literal_eval(string_template)
266                if not objects.has_key('SlapdManager'):
267                        return {'status':False,'msg':'This function depend on SlapdManager, but this is not installed or not working'}
268                result = objects['SlapdManager'].insert_dictionary(aux_dic,i_existing=True)
269                if not result['status']:
270                        return result
271                result = self.update_xid_counter("ou=Profiles,ou=Groups,"+environment_vars['LDAP_BASE_DN'],10005)
272                if result[0]:
273                        objects['VariablesManager'].init_variable('ENABLE_NSS_LDAP',{'ENABLE_NSS_LDAP':'ENABLED'})
274                        return {'status':True,'msg':'Load structure for education model'}
275                else:
276                        return {'status':False,'msg':result[1]}
277        #def load_education
278       
279        def configure_smb(self):
280                template = self.tpl_env.get_template('smb.conf')
281                if  objects.has_key("VariablesManager"):
282                        objects['VariablesManager'].init_variable('DEADTIME')
283                        objects['VariablesManager'].init_variable('SAMBA_DOMAIN_NAME')
284                        objects['VariablesManager'].init_variable('NAME_SERVER_SAMBA')
285                        environment_vars = objects["VariablesManager"].get_variable_list(['SAMBA_DOMAIN_NAME','NAME_SERVER_SAMBA','DEADTIME','LDAP_BASE_DN'])
286                string_template = template.render(environment_vars).encode('utf-8')
287                tmp,filename=tempfile.mkstemp()
288                f = open(filename,'w')
289                f.writelines(string_template)
290                f.close()
291                n4d_mv(filename,'/etc/samba/smb.conf')
292                return {'status':True,'msg':'Configured samba'}
293        #def configure_smb
294       
295        def load_acl_samba_education(self):
296                if os.path.exists(self.available_acl_path + 'all_samba'):
297                        installed_link = False
298                        if not os.path.exists(self.enable_acl_path + '600_all_samba'):
299                                os.symlink(self.available_acl_path + 'all_samba',self.enable_acl_path + '600_all_samba')
300                if os.path.exists(self.available_acl_path + 'subtree_students_samba'):
301                        installed_link = False
302                        if not os.path.exists(self.enable_acl_path + '400_subtree_students_samba'):
303                                os.symlink(self.available_acl_path + 'subtree_students_samba',self.enable_acl_path + '400_subtree_students_samba')
304                result = objects['SlapdManager'].load_acl()
305                if not result['status']:
306                        return result
307                return {'status':True,'msg':'Loaded acl'}
308        #def load_acl_samba
309       
310        def update_root_password_samba(self,password):
311                subprocess.Popen(['smbpasswd','-w',password],stdout=subprocess.PIPE).communicate()
312                return {'status':True,'msg':'Update root password on samba database'}
313        #def update_root_password_samba
314       
315        def insert_to_admin_profile(self,dn,uid):
316                if not self.test_ldap_connection():
317                        if not self.connection_ldap():
318                                return {"status":False,"msg":"Connection with ldap is not created"}
319                if  objects.has_key("VariablesManager"):
320                        environment_vars = objects["VariablesManager"].get_variable_list(['LDAP_BASE_DN'])
321                path = "cn=admins,ou=Profiles,ou=Groups,"+  environment_vars['LDAP_BASE_DN']
322                mod_list=[]
323                mod=(ldap.MOD_ADD,"memberUid",str(uid))
324                mod_list.append(mod)
325                for x in mod_list:
326                        try:
327                                self.connect_ldap.modify_s(path,[x])
328                        except ldap.ALREADY_EXISTS as e:
329                                pass
330                        except Exception as e:
331                                return {'status':False,'msg':'insert_to_admin_profile error :'+ str(e)}
332                return {'status':True,'msg':str(uid)+ 'has been added to admin profile'}
333        #def insert_to_admin_profile
334       
335        def insert_to_admin_groups(self, uid):
336                if not self.test_ldap_connection():
337                        if not self.connection_ldap():
338                                return {"status":False,"msg":"Connection with ldap is not created"}
339                if  objects.has_key("VariablesManager"):
340                        environment_vars = objects["VariablesManager"].get_variable_list(['LDAP_BASE_DN'])
341                system_admin_groups = ['sudo','adm','plugdev','lpadmin','cdrom','dip','epoptes']
342                for group in system_admin_groups:
343                        mod=(ldap.MOD_ADD,"memberUid",str(uid))
344                        group_path="cn=" + group +",ou=System,ou=Groups," + environment_vars['LDAP_BASE_DN']
345                        try:
346                                self.connect_ldap.modify_s(group_path,[mod])
347                        except ldap.ALREADY_EXISTS as e:
348                                pass
349                        except Exception as e:
350                                return {'status':False,'msg':'insert to admin group error :'+ str(e)}   
351                return {'status':True,'msg':'All ok'}
352
353        def set_sambasid(self,sambasid):
354                result = os.system('net setlocalsid ' + sambasid)
355                if result == 0:
356                        return{'status':True,'msg': 'SID ' + str(sambasid) + ' has been set'}
357                else:
358                        return{'status':False,'msg': 'SID could not change'}
359        '''
360                Internal Methods
361        '''
362
363        def test_ldap_connection(self):
364                try:
365                        self.connection_ldap.search_s('',ldap.SCOPE_BASE)
366                        return True
367                except:
368                        return False
369        #def test_ldap_connection
370
371
372        def connection_ldap(self):
373                try:
374                        self.connect_ldap=ldap.initialize('ldap://localhost:389',trace_level=0)
375                        self.connect_ldap.protocol_version=3
376                        if os.path.exists(self.LDAP_SECRET1):
377                                f=open(self.LDAP_SECRET1)
378                                lines=f.readlines()
379                                f.close()
380                                password=lines[0].replace("\n","")
381                        elif os.path.exists(self.LDAP_SECRET2):
382                                f=open(self.LDAP_SECRET2)
383                                lines=f.readlines()
384                                f.close()
385                                password=lines[0].replace("\n","")
386                        else:
387                                self.connect_ldap = None
388                                return False
389                        environment_vars = objects["VariablesManager"].get_variable_list(['LDAP_BASE_DN'])
390                        self.connect_ldap.bind_s("cn=admin,"+environment_vars['LDAP_BASE_DN'],password)
391                        return True
392                except Exception as e:
393                        print "\n\nError" + str(e) + "\n\n"
394                        self.connect_ldap = None
395                        return False
396
397        # def connection_ldap
Note: See TracBrowser for help on using the repository browser.