1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
import time
|
14
|
import locale
|
15
|
from shutil import rmtree
|
16
|
from os import system, makedirs, symlink, remove, chown, chmod, listdir, fchmod
|
17
|
from os.path import join, islink, isfile, basename, isdir, getmtime
|
18
|
from datetime import datetime
|
19
|
import ldap
|
20
|
|
21
|
from scribe.cadolesldapconf import ROOT_DN, ldap_server, ldap_passwd, SUFFIX, \
|
22
|
HOME_PATH, SMB_SERVEUR, USER_FILTER, GROUP_FILTER, SHARE_FILTER
|
23
|
|
24
|
PATH_SCRIPTS = '/home/netlogon/scripts'
|
25
|
SCRIPTS_EXT = '.txt'
|
26
|
|
27
|
def logon(user, ostype, machine, adresse_ip):
|
28
|
|
29
|
def ldap_search(ldap_filter, attrib=None, one=False):
|
30
|
result = ldap_conn.search_s(SUFFIX, ldap.SCOPE_SUBTREE,
|
31
|
ldap_filter, attrib)
|
32
|
if len(result) > 0 and len(result[0]) == 2:
|
33
|
if one:
|
34
|
return result[0][1]
|
35
|
else:
|
36
|
return result
|
37
|
else:
|
38
|
return {}
|
39
|
|
40
|
ldap_conn = ldap.open(ldap_server)
|
41
|
ldap_conn.simple_bind_s(ROOT_DN, ldap_passwd)
|
42
|
user_attrib = ldap_search("(&%s(uid=%s))" % (USER_FILTER, user),
|
43
|
['objectClass', 'homeDirectory', 'sambaHomeDrive', 'uidNumber',
|
44
|
'gidNumber'], True)
|
45
|
userclass = get_userclass_name(user_attrib.get('objectClass', None))
|
46
|
if not userclass:
|
47
|
raise Exception("utilisateur %s inconnu" % user)
|
48
|
|
49
|
if userclass not in ['administratif', 'eleve', 'enseignant']:
|
50
|
raise Exception("l'utilisateur %s n'est pas autorisé à se connecter" % user)
|
51
|
|
52
|
|
53
|
|
54
|
netlogon = '/home/netlogon/%s%s.txt' % (user, ostype)
|
55
|
if isfile(netlogon):
|
56
|
diff = time.time() - getmtime(netlogon)
|
57
|
else:
|
58
|
diff = 600
|
59
|
prim_group = None
|
60
|
gidnumber = user_attrib['gidNumber'][0].strip()
|
61
|
if diff > 60:
|
62
|
""" construction des scripts de connexion windows
|
63
|
le fichier est du format .bat pour Win95 et .txt pour le reste
|
64
|
"""
|
65
|
homedir = user_attrib['homeDirectory'][0].strip()
|
66
|
homedrive = user_attrib['sambaHomeDrive'][0].strip()
|
67
|
uid = int(user_attrib['uidNumber'][0].strip())
|
68
|
|
69
|
groups = []
|
70
|
group_filter = ''
|
71
|
for dn, grp in ldap_search("(&%s(memberUid=%s))" % (GROUP_FILTER, user),
|
72
|
attrib=['cn', 'gidNumber']):
|
73
|
name = grp['cn'][0]
|
74
|
if grp['gidNumber'][0] == gidnumber:
|
75
|
prim_group = name
|
76
|
groups.append(name)
|
77
|
group_filter += '(sambaShareGroup=%s)' % name
|
78
|
|
79
|
shares = []
|
80
|
for share in ldap_search('(&%s(|%s))' % (SHARE_FILTER, group_filter),
|
81
|
['sambaShareName', 'sambaFilePath', 'sambaShareURI',
|
82
|
'sambaShareDrive']):
|
83
|
if share[1].has_key('sambaShareDrive'):
|
84
|
drive = share[1]['sambaShareDrive'][0]
|
85
|
else:
|
86
|
drive = ''
|
87
|
shares.append({'name': share[1]['sambaShareName'][0],
|
88
|
'path': share[1]['sambaFilePath'][0],
|
89
|
'uri': share[1]['sambaShareURI'][0],
|
90
|
'drive': drive})
|
91
|
|
92
|
|
93
|
gen_fich(user, groups, shares, machine, ostype, homedrive, userclass,
|
94
|
netlogon)
|
95
|
|
96
|
gen_ftpdir(uid, homedir, shares)
|
97
|
|
98
|
gen_groupedir(uid, homedir, shares)
|
99
|
|
100
|
gen_devdir(user, uid, homedir, userclass)
|
101
|
|
102
|
if not prim_group:
|
103
|
prim_group = ldap_search("(&%s(gidNumber=%s))" % (GROUP_FILTER,
|
104
|
gidnumber), ['displayName'], True)['displayName'][0]
|
105
|
ldap_conn.unbind()
|
106
|
|
107
|
|
108
|
|
109
|
|
110
|
log_connexion(user, prim_group, machine, ostype, adresse_ip)
|
111
|
|
112
|
def get_userclass_name(objectClass):
|
113
|
"""
|
114
|
Renvoie le nom du module gérant les objets de classe : objectClass
|
115
|
"""
|
116
|
if objectClass == None:
|
117
|
return None
|
118
|
users_objectClass = {
|
119
|
'Eleves': 'eleve',
|
120
|
'administrateur': 'enseignant',
|
121
|
'responsable': 'responsable',
|
122
|
'administratif': 'administratif',
|
123
|
'autre': 'autre',
|
124
|
}
|
125
|
for objectclass, module in users_objectClass.items():
|
126
|
if objectclass in objectClass:
|
127
|
return module
|
128
|
return None
|
129
|
|
130
|
def gen_devdir(login, uid, homedir, userclass):
|
131
|
"""
|
132
|
Partie commune pour _gen_devoirdir
|
133
|
"""
|
134
|
if userclass not in ['eleve', 'enseignant']:
|
135
|
return
|
136
|
perso = join(homedir, 'perso')
|
137
|
|
138
|
dev_part = join(homedir, 'devoirs')
|
139
|
|
140
|
dev_perso = join(perso, 'devoirs')
|
141
|
cmd = ""
|
142
|
for rep in [dev_part, dev_perso]:
|
143
|
if islink(rep):
|
144
|
remove(rep)
|
145
|
if not isdir(rep):
|
146
|
makedirs(rep, 0750)
|
147
|
else:
|
148
|
cmd += '/bin/chmod -R 0750 %s;' % rep
|
149
|
cmd += '/bin/chown -PR %s %s;' % (login, rep)
|
150
|
cmd += '/usr/bin/setfacl -PRm u:%s:rwx %s;'%(uid, rep)
|
151
|
cmd += '/usr/bin/setfacl -dPRm u:%s:rwx %s;'%(uid, rep)
|
152
|
|
153
|
if userclass == 'enseignant':
|
154
|
|
155
|
|
156
|
dev_dist_dir = join(HOME_PATH, 'workgroups/devoirs', login)
|
157
|
if not isdir(dev_dist_dir):
|
158
|
makedirs(dev_dist_dir, 0755)
|
159
|
else:
|
160
|
cmd += '/bin/chmod -R 0755 %s;' % dev_dist_dir
|
161
|
cmd += '/usr/bin/setfacl -PRbk %s;' % dev_dist_dir
|
162
|
cmd += '/usr/bin/setfacl -PRm u:%s:rwx %s;' % (uid, dev_dist_dir)
|
163
|
cmd += '/usr/bin/setfacl -dPRm u:%s:rwx %s;' % (uid, dev_dist_dir)
|
164
|
for rep in [dev_part, dev_perso]:
|
165
|
link = join(rep, '.distribues')
|
166
|
if not islink(link):
|
167
|
symlink(dev_dist_dir, link)
|
168
|
system(cmd)
|
169
|
|
170
|
def gen_ftpdir(uid, homedir, shares):
|
171
|
"""
|
172
|
Gestion du répertoire ".ftp"
|
173
|
"""
|
174
|
ftpdir = join(homedir, '.ftp')
|
175
|
if isdir(ftpdir):
|
176
|
rmtree(ftpdir)
|
177
|
makedirs(ftpdir, 0500)
|
178
|
chown(ftpdir, uid, -1)
|
179
|
|
180
|
|
181
|
|
182
|
homedir = join(HOME_PATH, homedir[6:])
|
183
|
symlink(join(homedir, 'perso'), join(ftpdir, 'perso'))
|
184
|
for share in shares:
|
185
|
if share['name'] not in ['icones$', 'groupes']:
|
186
|
if HOME_PATH != '/home':
|
187
|
share['path'] = share['path'].replace('/home',
|
188
|
HOME_PATH)
|
189
|
symlink(share['path'], join(ftpdir, share['name']))
|
190
|
|
191
|
def gen_groupedir(uid, homedir, shares):
|
192
|
"""
|
193
|
Gestion du répertoire "groupes"
|
194
|
"""
|
195
|
groupedir = join(homedir, 'groupes')
|
196
|
if isdir(groupedir):
|
197
|
rmtree(groupedir)
|
198
|
makedirs(groupedir, 0500)
|
199
|
chown(groupedir, uid, -1)
|
200
|
|
201
|
|
202
|
for share in shares:
|
203
|
|
204
|
if share['drive'] == "":
|
205
|
|
206
|
symlink(share['path'], join(groupedir, share['name']))
|
207
|
|
208
|
def log_connexion(user, primgrp, machine, ostype, adresse_ip):
|
209
|
"""
|
210
|
Enregistrement de la connexion
|
211
|
"""
|
212
|
locale.setlocale(locale.LC_ALL, '')
|
213
|
try:
|
214
|
sdate = datetime.now().strftime("%a %d %b %Y %H:%M").capitalize()
|
215
|
cmd = 'echo CONNECTION %s %s %s %s %s %s' % (sdate, user,
|
216
|
primgrp, machine, ostype, adresse_ip)
|
217
|
system('%s >> /var/log/samba/%s.log' % (cmd, machine))
|
218
|
system('%s >> /var/log/samba/connexions.log' % (cmd))
|
219
|
except:
|
220
|
pass
|
221
|
|
222
|
|
223
|
|
224
|
|
225
|
|
226
|
def gen_fich(user, groups, shares, machine, ostype, homedrive, userclass,
|
227
|
netlogon):
|
228
|
"""
|
229
|
Génération du fichier lu par le client
|
230
|
"""
|
231
|
script = ""
|
232
|
|
233
|
for share in shares:
|
234
|
|
235
|
if share['drive'] != "":
|
236
|
|
237
|
if ostype == "Win95":
|
238
|
script += gen_lecteur_bloc_win95(share['drive'],
|
239
|
share['uri'])
|
240
|
else:
|
241
|
script += gen_lecteur_bloc(share['drive'], share['uri'])
|
242
|
|
243
|
|
244
|
if ostype in ['Win95', 'Samba']:
|
245
|
script += gen_lecteur_bloc_win95(homedrive, '\\\\%s\\PERSO' %
|
246
|
SMB_SERVEUR)
|
247
|
|
248
|
if ostype == 'Win95':
|
249
|
"""Gestion "à l'ancienne" pour Win9x/Me
|
250
|
exécuté par le service et logon.py(.exe) sur les clients
|
251
|
"""
|
252
|
script += gen_vnc_line(userclass)
|
253
|
script += gen_esu()
|
254
|
|
255
|
|
256
|
debut, fin = get_scripts(user, machine, ostype, groups)
|
257
|
|
258
|
write_fich(netlogon, debut + script + fin)
|
259
|
|
260
|
def gen_letter_share(lettre, share):
|
261
|
"""lettre : supprime les ":", juste la lettre
|
262
|
share : le partage sans \ à la fin
|
263
|
"""
|
264
|
while share[-1] == '\\':
|
265
|
share = share[:-1]
|
266
|
return lettre[:1], share
|
267
|
|
268
|
def gen_lecteur_bloc(lettre, share):
|
269
|
"""Génère un bloc de ligne pour le montage
|
270
|
d'un lecteur réseau "share" sur la lettre "lettre"
|
271
|
ou sur * sinon (sauf pour win95)
|
272
|
"""
|
273
|
lettre, share = gen_letter_share(lettre, share)
|
274
|
return 'lecteur,%s:,%s\r\n' % (lettre, share)
|
275
|
|
276
|
def gen_cmd_line(line, hide=False, nowait=False):
|
277
|
"""génère une ligne DOS (avec le bon retour chariot) (pas win95)
|
278
|
"""
|
279
|
chaine = 'cmd,%s' % line
|
280
|
if hide:
|
281
|
chaine += ',HIDDEN'
|
282
|
if nowait:
|
283
|
chaine += ',NOWAIT'
|
284
|
return chaine + '\r\n'
|
285
|
|
286
|
def get_scripts(user, machine, ostype, user_groups):
|
287
|
"""Gestion des scripts externes
|
288
|
"""
|
289
|
|
290
|
|
291
|
motif_include = [ "%%NetUse%%", "%NetUse%" ]
|
292
|
|
293
|
buffer_debut, buffer_fin = '', ''
|
294
|
|
295
|
for chemin in get_scripts_list(user, machine, ostype, user_groups):
|
296
|
if isfile(chemin):
|
297
|
debut = 1
|
298
|
for line in file(chemin,"r"):
|
299
|
line = line.strip()
|
300
|
if line in motif_include:
|
301
|
debut = 0
|
302
|
else:
|
303
|
if debut == 1:
|
304
|
buffer_debut += parse_line(ostype, line)
|
305
|
else:
|
306
|
buffer_fin += parse_line(ostype, line)
|
307
|
return (buffer_debut, buffer_fin)
|
308
|
|
309
|
def get_scripts_list(user, machine, ostype, user_groups):
|
310
|
"""On créé la liste des fichiers possibles
|
311
|
+--PATH_SCRIPTS/users/<user>.txt
|
312
|
+--PATH_SCRIPTS/groups/<group>.txt
|
313
|
+--PATH_SCRIPTS/machines/<machine>.txt
|
314
|
+--PATH_SCRIPTS/os/<os>.txt
|
315
|
+--PATH_SCRIPTS/os/<os>/<group>.txt
|
316
|
+--PATH_SCRIPTS/os/<os>/<user>.txt
|
317
|
"""
|
318
|
chemins = [join(PATH_SCRIPTS, 'users', '%s%s' % (user, SCRIPTS_EXT))]
|
319
|
chemins.append(join(PATH_SCRIPTS, 'machines', '%s%s' %
|
320
|
(machine, SCRIPTS_EXT)))
|
321
|
for group in user_groups:
|
322
|
chemins.append(join(PATH_SCRIPTS, 'groups', '%s%s' %
|
323
|
(group, SCRIPTS_EXT)))
|
324
|
chemins.append(join(PATH_SCRIPTS, 'os', '%s' % ostype, '%s%s' %
|
325
|
(group, SCRIPTS_EXT)))
|
326
|
chemins.append(join(PATH_SCRIPTS, 'os', '%s%s' % (ostype, SCRIPTS_EXT)))
|
327
|
chemins.append(join(PATH_SCRIPTS, 'os', ostype, '%s%s' %
|
328
|
(user, SCRIPTS_EXT)))
|
329
|
return chemins
|
330
|
|
331
|
def parse_line(ostype, line):
|
332
|
items = [ i.strip() for i in line.split(',') ]
|
333
|
if items[0] == 'cmd':
|
334
|
|
335
|
if ostype == "Win95":
|
336
|
return gen_cmd_line_win95(items[1])
|
337
|
else:
|
338
|
hide = 'HIDDEN' in items
|
339
|
nowait = 'NOWAIT' in items
|
340
|
return gen_cmd_line(items[1], hide, nowait)
|
341
|
|
342
|
elif items[0] == 'lecteur':
|
343
|
|
344
|
lettre, partage = items[1], items[2]
|
345
|
if ostype == "Win95":
|
346
|
return gen_lecteur_bloc_win95(lettre, partage)
|
347
|
else:
|
348
|
return gen_lecteur_bloc(lettre, partage)
|
349
|
return ''
|
350
|
|
351
|
def write_fich(netlogon, lines):
|
352
|
"""Ecrit le fichier
|
353
|
"""
|
354
|
fic = file(netlogon, 'w')
|
355
|
fchmod(fic.fileno(), 0644)
|
356
|
|
357
|
|
358
|
lines = lines.decode('utf8').encode('cp437')
|
359
|
fic.write(lines)
|
360
|
fic.close()
|
361
|
|
362
|
|
363
|
|
364
|
|
365
|
def test_esu():
|
366
|
"""
|
367
|
vérifie si Esu est utilisé
|
368
|
"""
|
369
|
for fic in listdir('/home/esu/Base'):
|
370
|
if fic.lower() == 'esuclnt.exe':
|
371
|
return True
|
372
|
return False
|
373
|
|
374
|
def gen_esu():
|
375
|
"""Ajoute la ligne pour Esu pour win95
|
376
|
"""
|
377
|
if test_esu():
|
378
|
esuline = '\\\\%s\\ESU\\Base\\esuclnt.exe' % SMB_SERVEUR
|
379
|
return gen_cmd_line_win95(esuline)
|
380
|
return ''
|
381
|
|
382
|
def gen_vnc_line(userclass):
|
383
|
"""VNC utilise maintenant login/pass du domaine
|
384
|
ce .reg spécifie le type de controle possible$
|
385
|
(desactive, simple, controle) lors de l'observation pour les Win95
|
386
|
"""
|
387
|
vnccontrole = 'regedit /s \\\\%s\\netlogon\\scripts\\os\\Win95\\vnc_controle.reg' % SMB_SERVEUR
|
388
|
vnckill = '%windir%\\eole\\ultravnc\\winvnc -kill'
|
389
|
vncservice = '%windir%\\eole\\ultravnc\\winvnc -service'
|
390
|
bloc = gen_cmd_line_win95(vnccontrole)
|
391
|
bloc += gen_cmd_line_win95(vnckill)
|
392
|
if userclass == 'eleve':
|
393
|
bloc += gen_cmd_line_win95(vncservice)
|
394
|
return bloc
|
395
|
|
396
|
def gen_cmd_line_win95(line):
|
397
|
"""génère une ligne DOS Win95 (avec le bon retour chariot)
|
398
|
"""
|
399
|
saut_ligne = chr(13)+chr(10)
|
400
|
return '%s%s' % (line, saut_ligne)
|
401
|
|
402
|
def gen_lecteur_bloc_win95(lettre, share):
|
403
|
"""Génère un bloc de ligne pour le montage
|
404
|
d'un lecteur réseau "share" sur la lettre "lettre"
|
405
|
ou sur * sinon pour win95
|
406
|
"""
|
407
|
lettre, share = gen_letter_share(lettre, share)
|
408
|
sharename = share.split('\\')[-1].replace('$', '')
|
409
|
|
410
|
label = '%s%s' % (lettre, sharename)
|
411
|
chaine_net_use = 'NET USE '
|
412
|
bloc = gen_cmd_line_win95('IF EXIST %s:\\nul goto err%s' % (lettre, label))
|
413
|
bloc += gen_cmd_line_win95('%s %s: %s'%(chaine_net_use, lettre, share))
|
414
|
bloc += gen_cmd_line_win95('goto suit%s'%(label))
|
415
|
bloc += gen_cmd_line_win95(':err%s'%(label))
|
416
|
bloc += gen_cmd_line_win95('%s * %s'%(chaine_net_use, share))
|
417
|
bloc += gen_cmd_line_win95(':suit%s'%(label))
|
418
|
return bloc
|
419
|
|