[gest_crans_lc] Gestion des certificats++, gestion des Ctrl-c
This commit is contained in:
parent
a8a1767844
commit
227389ae73
1 changed files with 364 additions and 59 deletions
|
@ -15,6 +15,7 @@ Licence : GPLv3
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import ssl
|
||||||
import time
|
import time
|
||||||
import ldap
|
import ldap
|
||||||
import signal
|
import signal
|
||||||
|
@ -24,7 +25,9 @@ import collections
|
||||||
sys.path.append('/usr/scripts/')
|
sys.path.append('/usr/scripts/')
|
||||||
from pythondialog import Dialog
|
from pythondialog import Dialog
|
||||||
from pythondialog import DialogError
|
from pythondialog import DialogError
|
||||||
|
from OpenSSL import crypto, SSL
|
||||||
|
|
||||||
|
from gestion.cert_utils import createCertRequest
|
||||||
from gestion.affich_tools import get_screen_size, coul
|
from gestion.affich_tools import get_screen_size, coul
|
||||||
from gestion.chgpass import checkpass
|
from gestion.chgpass import checkpass
|
||||||
import gestion.config as config
|
import gestion.config as config
|
||||||
|
@ -37,8 +40,9 @@ import lc_ldap.crans_utils as lc_utils
|
||||||
|
|
||||||
from lc_ldap.attributs import UniquenessError
|
from lc_ldap.attributs import UniquenessError
|
||||||
|
|
||||||
|
import gestion.secrets_new as secrets
|
||||||
debugf=None
|
debugf=None
|
||||||
debug_enable = True
|
debug_enable = False
|
||||||
|
|
||||||
def mydebug(txt):
|
def mydebug(txt):
|
||||||
global debugf, debug_enable
|
global debugf, debug_enable
|
||||||
|
@ -166,7 +170,7 @@ def handle_exit_code(d, code):
|
||||||
os.system('clear')
|
os.system('clear')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
msg = "Vous avez appuyer sur ESC dans la dernière fenêtre de dialogue.\n\n" \
|
msg = "Vous avez appuyer sur ESC ou CTRL+C dans la dernière fenêtre de dialogue.\n\n" \
|
||||||
"Voulez vous quitter le programme ?"
|
"Voulez vous quitter le programme ?"
|
||||||
if d.yesno(msg, width=60) == d.DIALOG_OK:
|
if d.yesno(msg, width=60) == d.DIALOG_OK:
|
||||||
os.system('clear')
|
os.system('clear')
|
||||||
|
@ -175,6 +179,8 @@ def handle_exit_code(d, code):
|
||||||
else:
|
else:
|
||||||
return True # code est d.DIALOG_OK
|
return True # code est d.DIALOG_OK
|
||||||
|
|
||||||
|
def raiseKeyboardInterrupt(x, y):
|
||||||
|
raise KeyboardInterrupt()
|
||||||
|
|
||||||
class GestCrans(object):
|
class GestCrans(object):
|
||||||
"""Interface de gestion des machines et des adhérents du crans, version lc_ldap"""
|
"""Interface de gestion des machines et des adhérents du crans, version lc_ldap"""
|
||||||
|
@ -188,8 +194,7 @@ class GestCrans(object):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if not debug_enable:
|
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
||||||
# On initialise le moteur de rendu en spécifiant qu'on va faire du dialog
|
# On initialise le moteur de rendu en spécifiant qu'on va faire du dialog
|
||||||
printing.template(dialog=True)
|
printing.template(dialog=True)
|
||||||
|
|
||||||
|
@ -202,7 +207,7 @@ class GestCrans(object):
|
||||||
self.check_ldap_last = time.time()
|
self.check_ldap_last = time.time()
|
||||||
# On ouvre une connexion lc_ldap
|
# On ouvre une connexion lc_ldap
|
||||||
self.conn = lc_ldap.shortcuts.lc_ldap_admin()
|
self.conn = lc_ldap.shortcuts.lc_ldap_admin()
|
||||||
self.conn.current_login = 'totocrans'
|
#self.conn.current_login = 'totocrans'
|
||||||
# On vérifie que l'utilisateur système existe dans ldap (pour la gestion des droits)
|
# On vérifie que l'utilisateur système existe dans ldap (pour la gestion des droits)
|
||||||
luser=self.conn.search(u'(&(uid=%s)(objectClass=cransAccount))' % self.conn.current_login)
|
luser=self.conn.search(u'(&(uid=%s)(objectClass=cransAccount))' % self.conn.current_login)
|
||||||
if not luser:
|
if not luser:
|
||||||
|
@ -222,6 +227,26 @@ class GestCrans(object):
|
||||||
self.dialog_last_access = time.time()
|
self.dialog_last_access = time.time()
|
||||||
return self._dialog
|
return self._dialog
|
||||||
|
|
||||||
|
@tailcaller
|
||||||
|
def handle_dialog(self, cancel_cont, box, *args):
|
||||||
|
ctrlC=False
|
||||||
|
ret=None
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGINT, raiseKeyboardInterrupt) # Ctrl-C
|
||||||
|
ret = box(*args)
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
|
||||||
|
ctrlC = True
|
||||||
|
finally:
|
||||||
|
if ctrlC:
|
||||||
|
raise Continue(cancel_cont)
|
||||||
|
elif ret:
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
EnvironmentError("Ni Ctrl+C ni ret ?!? c'est pas possible ")
|
||||||
|
|
||||||
|
@tailcaller
|
||||||
def handle_dialog_result(self, code, output, cancel_cont, error_cont, codes_todo=[]):
|
def handle_dialog_result(self, code, output, cancel_cont, error_cont, codes_todo=[]):
|
||||||
""" codes_todo = [(code, todo, todo_args)]"""
|
""" codes_todo = [(code, todo, todo_args)]"""
|
||||||
# Si on a appuyé sur annulé ou ESC, on s'en va via la continuation donnée en argument
|
# Si on a appuyé sur annulé ou ESC, on s'en va via la continuation donnée en argument
|
||||||
|
@ -232,15 +257,23 @@ class GestCrans(object):
|
||||||
for (codes, todo, todo_args) in codes_todo:
|
for (codes, todo, todo_args) in codes_todo:
|
||||||
if code in codes:
|
if code in codes:
|
||||||
try:
|
try:
|
||||||
|
signal.signal(signal.SIGINT, raiseKeyboardInterrupt) # Ctrl-C
|
||||||
# On effectue ce qu'il y a a faire dans todo
|
# On effectue ce qu'il y a a faire dans todo
|
||||||
return todo(*todo_args)
|
ret = todo(*todo_args)
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
|
||||||
|
return ret
|
||||||
# On propage les Continue
|
# On propage les Continue
|
||||||
except self.error_to_raise:
|
except self.error_to_raise:
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
|
||||||
raise
|
raise
|
||||||
# En cas d'une autre erreur, on l'affiche et on retourne au menu d'édition
|
# En cas d'une autre erreur, on l'affiche et on retourne au menu d'édition
|
||||||
except (Exception, ldap.OBJECT_CLASS_VIOLATION) as e:
|
except (Exception, ldap.OBJECT_CLASS_VIOLATION) as e:
|
||||||
self.dialog.msgbox("%s" % unicode_of_Error(e), timeout=self.timeout,title="Erreur rencontrée", width=73, height=10)
|
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
|
||||||
raise Continue(error_cont)
|
self.dialog.msgbox("%s" % unicode_of_Error(e), timeout=self.timeout,title="Erreur rencontrée", width=73, height=10)
|
||||||
|
raise Continue(error_cont)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_IGN) # Pas de Ctrl-C
|
||||||
|
raise Continue(cancel_cont)
|
||||||
|
|
||||||
# En cas de code de retour dialog non attendu, on prévient et on retourne au menu d'édition
|
# En cas de code de retour dialog non attendu, on prévient et on retourne au menu d'édition
|
||||||
self.dialog.msgbox("Le code de retour dialog est %s, c'est étrange" % code, timeout=self.timeout, title="Erreur rencontrée", width=73, height=10)
|
self.dialog.msgbox("Le code de retour dialog est %s, c'est étrange" % code, timeout=self.timeout, title="Erreur rencontrée", width=73, height=10)
|
||||||
|
@ -282,7 +315,7 @@ class GestCrans(object):
|
||||||
return tag, bl
|
return tag, bl
|
||||||
|
|
||||||
|
|
||||||
(code, tag) = box()
|
(code, tag) = self.handle_dialog(cont, box)
|
||||||
retry_cont = TailCall(self.edit_blacklist_select, obj=obj, title=title, cont=cont)
|
retry_cont = TailCall(self.edit_blacklist_select, obj=obj, title=title, cont=cont)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -319,7 +352,7 @@ class GestCrans(object):
|
||||||
self.dialog.msgbox("%s n'est pas une blacklist" % tag, timeout=self.timeout, title="Erreur rencontrée", width=73, height=10)
|
self.dialog.msgbox("%s n'est pas une blacklist" % tag, timeout=self.timeout, title="Erreur rencontrée", width=73, height=10)
|
||||||
raise Continue(retry_cont)
|
raise Continue(retry_cont)
|
||||||
|
|
||||||
(code, tag) = box()
|
(code, tag) = self.handle_dialog(cont, box)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
output=tag,
|
output=tag,
|
||||||
|
@ -544,7 +577,7 @@ class GestCrans(object):
|
||||||
if values is None:
|
if values is None:
|
||||||
values = [str(a) for a in obj[attr]]
|
values = [str(a) for a in obj[attr]]
|
||||||
retry_cont = TailCall(self.edit_attributs, obj=obj, attr=attr, title=title, update_obj=update_obj, cont=cont, values=values)
|
retry_cont = TailCall(self.edit_attributs, obj=obj, attr=attr, title=title, update_obj=update_obj, cont=cont, values=values)
|
||||||
(code, output) = box(values, tag)
|
(code, output) = self.handle_dialog(cont, box, values, tag)
|
||||||
|
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -605,7 +638,7 @@ class GestCrans(object):
|
||||||
else: # empty selection
|
else: # empty selection
|
||||||
return (code, [])
|
return (code, [])
|
||||||
|
|
||||||
(code, dialog_values) = box()
|
(code, dialog_values) = self.handle_dialog(cont, box)
|
||||||
# Si il a appuyé sur annuler ou sur escape, on saute sur la continuation
|
# Si il a appuyé sur annuler ou sur escape, on saute sur la continuation
|
||||||
if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC):
|
if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC):
|
||||||
raise Continue(cont)
|
raise Continue(cont)
|
||||||
|
@ -724,7 +757,7 @@ class GestCrans(object):
|
||||||
else:
|
else:
|
||||||
raise Continue(cont)
|
raise Continue(cont)
|
||||||
|
|
||||||
(code, tag) = box(items, default_item)
|
(code, tag) = self.handle_dialog(cont, box, items, default_item)
|
||||||
retry_cont = TailCall(self.select_one, items=items, title=title, default_item=tag, cont=cont)
|
retry_cont = TailCall(self.select_one, items=items, title=title, default_item=tag, cont=cont)
|
||||||
|
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
|
@ -885,7 +918,7 @@ class GestCrans(object):
|
||||||
machine.save()
|
machine.save()
|
||||||
return machine
|
return machine
|
||||||
|
|
||||||
def create_machine(prorio, realm, attrs):
|
def create_machine(proprio, realm, attrs):
|
||||||
# Dans ce cas, on a besoin d'un proprio et d'un realm pour déterminer le rid
|
# Dans ce cas, on a besoin d'un proprio et d'un realm pour déterminer le rid
|
||||||
if proprio is None or realm is None:
|
if proprio is None or realm is None:
|
||||||
raise EnvironmentError("On essaye de créer une machine mais proprio ou realm vaut None")
|
raise EnvironmentError("On essaye de créer une machine mais proprio ou realm vaut None")
|
||||||
|
@ -925,14 +958,14 @@ class GestCrans(object):
|
||||||
machine = modif_machine(machine, attrs)
|
machine = modif_machine(machine, attrs)
|
||||||
# Soit on crée une nouvelle machine
|
# Soit on crée une nouvelle machine
|
||||||
else:
|
else:
|
||||||
machine = create_machine(prorio, realm, attrs)
|
machine = create_machine(proprio, realm, attrs)
|
||||||
raise Continue(cont(machine=machine))
|
raise Continue(cont(machine=machine))
|
||||||
|
|
||||||
|
|
||||||
if machine:
|
if machine:
|
||||||
objectClass = machine["objectClass"][0]
|
objectClass = machine["objectClass"][0]
|
||||||
|
|
||||||
(code, tags) = box()
|
(code, tags) = self.handle_dialog(cont, box)
|
||||||
|
|
||||||
# On prépare les fiels à afficher à l'utilisateur si une erreure à lieu
|
# On prépare les fiels à afficher à l'utilisateur si une erreure à lieu
|
||||||
# pendant le traitement des donnée (on n'éfface pas ce qui a déjà été entré
|
# pendant le traitement des donnée (on n'éfface pas ce qui a déjà été entré
|
||||||
|
@ -1002,7 +1035,7 @@ les valeurs valident sont :
|
||||||
certificat.save()
|
certificat.save()
|
||||||
raise Continue(cont(certificat=certificat))
|
raise Continue(cont(certificat=certificat))
|
||||||
|
|
||||||
(code, output) = box(values)
|
(code, output) = self.handle_dialog(cont, box, values)
|
||||||
values = dict(zip([form[k]['ldap_name'] for k in form_order], output))
|
values = dict(zip([form[k]['ldap_name'] for k in form_order], output))
|
||||||
fields_values = [("%s : " % k, values.get(form[k]['ldap_name'], ""), form[k]['len'] + 1, form[k]['len']) for k in form_order]
|
fields_values = [("%s : " % k, values.get(form[k]['ldap_name'], ""), form[k]['len'] + 1, form[k]['len']) for k in form_order]
|
||||||
self_cont=TailCall(self.certificat_tlsa, certificat=certificat, cont=cont, values=fields_values)
|
self_cont=TailCall(self.certificat_tlsa, certificat=certificat, cont=cont, values=fields_values)
|
||||||
|
@ -1014,8 +1047,10 @@ les valeurs valident sont :
|
||||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [form, values, certificat, cont])]
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [form, values, certificat, cont])]
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_certificat(self, machine, cont):
|
def create_certificat(self, cont, machine=None, certificat=None):
|
||||||
"""Permet d'ajouter un certificat à une machine à partir du PEM du certificat"""
|
"""Permet d'ajouter un certificat à une machine à partir du PEM du certificat"""
|
||||||
|
if machine is None and certificat is None:
|
||||||
|
raise EnvironmentError("Il faut fournir au moins une machine ou un certificat")
|
||||||
# input multiline en utilisant un editbox
|
# input multiline en utilisant un editbox
|
||||||
def box():
|
def box():
|
||||||
fp, path = tempfile.mkstemp()
|
fp, path = tempfile.mkstemp()
|
||||||
|
@ -1032,20 +1067,116 @@ les valeurs valident sont :
|
||||||
else:
|
else:
|
||||||
return code, None
|
return code, None
|
||||||
|
|
||||||
def todo(machine, cont):
|
def todo(machine, certificat, cont):
|
||||||
with self.conn.newCertificat(machine.dn, {}) as certificat:
|
if certificat:
|
||||||
certificat['certificat'] = unicode(pem, 'utf-8')
|
with self.conn.search(dn=certificat.dn, scope=0, mode='rw')[0] as certificat:
|
||||||
certificat.create()
|
certificat['certificat'] = unicode(pem, 'utf-8')
|
||||||
|
certificat.save()
|
||||||
|
else:
|
||||||
|
with self.conn.newCertificat(machine.dn, {}) as certificat:
|
||||||
|
certificat['certificat'] = unicode(pem, 'utf-8')
|
||||||
|
certificat.create()
|
||||||
raise Continue(cont(certificat=certificat, machine=certificat.machine()))
|
raise Continue(cont(certificat=certificat, machine=certificat.machine()))
|
||||||
|
|
||||||
(code, pem) = box()
|
(code, pem) = self.handle_dialog(cont, box)
|
||||||
self_cont = TailCall(self.create_certificat, machine=machine, cont=cont)
|
self_cont = TailCall(self.create_certificat, machine=machine, certificat=certificat, cont=cont)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
output=pem,
|
output=pem,
|
||||||
cancel_cont=cont,
|
cancel_cont=cont,
|
||||||
error_cont=self_cont,
|
error_cont=self_cont,
|
||||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [machine, cont])]
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [machine, certificat, cont])]
|
||||||
|
)
|
||||||
|
|
||||||
|
@tailcaller
|
||||||
|
def get_password(self, cont, confirm=True):
|
||||||
|
def todo(self_cont, cont):
|
||||||
|
(code, pass1) = self.dialog.passwordbox("Entrez un mot de passe", title="Choix d'un mot de passe")
|
||||||
|
if code != self.dialog.DIALOG_OK:
|
||||||
|
raise Continue(cont)
|
||||||
|
if confirm:
|
||||||
|
(code, pass2) = self.dialog.passwordbox("Comfirmer le mot de passe", title="Choix d'un mot de passe")
|
||||||
|
if code != self.dialog.DIALOG_OK:
|
||||||
|
raise Continue(self_cont)
|
||||||
|
if pass1 != pass2:
|
||||||
|
raise ValueError("Les deux mots de passe ne concordent pas")
|
||||||
|
return pass1
|
||||||
|
self_cont = TailCall(self.get_password, cont=cont)
|
||||||
|
return self.handle_dialog_result(
|
||||||
|
code=self.dialog.DIALOG_OK,
|
||||||
|
output="",
|
||||||
|
cancel_cont=cont,
|
||||||
|
error_cont=self_cont,
|
||||||
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [self_cont, cont])]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def create_privatekey(self, cont, machine=None, certificat=None, imp=False, size=4096):
|
||||||
|
"""Permet de générer ou importer une clef privée à une machine"""
|
||||||
|
if machine is None and certificat is None:
|
||||||
|
raise EnvironmentError("Il faut fournir au moins une machine ou un certificat")
|
||||||
|
# input multiline en utilisant un editbox
|
||||||
|
def box():
|
||||||
|
fp, path = tempfile.mkstemp()
|
||||||
|
os.close(fp)
|
||||||
|
cmd = ['--editbox', path, "0", "0"]
|
||||||
|
(code, output) = self.dialog._perform(*(cmd,),
|
||||||
|
no_mouse=True, # On désactive la sourie sinon dialog segfault si on clic
|
||||||
|
backtitle="Appuyez sur CTRL+MAJ+V pour coller",
|
||||||
|
timeout=self.timeout,
|
||||||
|
title="Création d'un certificat, entrez le PEM du certificat")
|
||||||
|
os.remove(path)
|
||||||
|
if code == self.dialog.DIALOG_OK:
|
||||||
|
return code, output
|
||||||
|
else:
|
||||||
|
return code, None
|
||||||
|
|
||||||
|
def todo(machine, certificat, pem, imp, size, cont):
|
||||||
|
if not imp:
|
||||||
|
if not machine:
|
||||||
|
machine=certificat.machine()
|
||||||
|
if "machineCrans" in machine['objectClass']:
|
||||||
|
passphrase = secrets.get('privatekey_passphrase')
|
||||||
|
else:
|
||||||
|
self.dialog.msgbox("Vous aller être inviter à entrez un mot de passe. Ce mot de passe est utilisé pour chiffrer la clef privée qui va être générée dans la base de donnée du crans.\n\nCe mot de passe n'est pas conservé, sous quelque forme que se soit par le crans.\nAussi, en cas de perte, la clef privée deviendrait inutilisable.\n Pensez à le sauvegarder quelque part",
|
||||||
|
title="Génération d'une clée privée",
|
||||||
|
width=70,
|
||||||
|
height=12)
|
||||||
|
passphrase = self.get_password(cont)
|
||||||
|
self.dialog.infobox("Génération d'une clef privée RSA de taille %s en cours.\nMerci de patienter" % size)
|
||||||
|
pem = crypto.PKey()
|
||||||
|
pem.generate_key(crypto.TYPE_RSA, size)
|
||||||
|
pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, pem, "des3", passphrase)
|
||||||
|
elif not pem.startswith("-----BEGIN ENCRYPTED PRIVATE KEY-----"):
|
||||||
|
raise ValueError("On n'accepte que des clef chiffrée PKCS#8 en PEM. Donc la clef doit commencer par -----BEGIN ENCRYPTED PRIVATE KEY-----")
|
||||||
|
if certificat:
|
||||||
|
if "privatekey" in certificat:
|
||||||
|
raise ValueError("Il y a déjà une clef privée, merci d'annuler")
|
||||||
|
with self.conn.search(dn=certificat.dn, scope=0, mode='rw')[0] as certificat:
|
||||||
|
certificat.private(pem, encrypted=True)
|
||||||
|
certificat.save()
|
||||||
|
self.dialog.msgbox("Clef privée bien ajouté", title="Ajout d'une clef privée")
|
||||||
|
raise Continue(cont(certificat=certificat, machine=certificat.machine()))
|
||||||
|
else:
|
||||||
|
with self.conn.newCertificat(machine.dn, {}) as certificat:
|
||||||
|
certificat['hostCert']=unicode(machine['host'][0])
|
||||||
|
certificat.private(pem, encrypted=True)
|
||||||
|
certificat.create()
|
||||||
|
self.dialog.msgbox("Clef privée créée avec succès", title="Création d'une clef privée")
|
||||||
|
raise Continue(cont(certificat=certificat, machine=certificat.machine()))
|
||||||
|
|
||||||
|
if imp:
|
||||||
|
(code, pem) = self.handle_dialog(cont, box)
|
||||||
|
else:
|
||||||
|
(code, pem) = (self.dialog.DIALOG_OK, "")
|
||||||
|
self_cont = TailCall(self.create_privatekey, machine=machine, certificat=certificat, cont=cont, imp=imp, size=size)
|
||||||
|
return self.handle_dialog_result(
|
||||||
|
code=code,
|
||||||
|
output=pem,
|
||||||
|
cancel_cont=cont,
|
||||||
|
error_cont=self_cont,
|
||||||
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [machine, certificat, pem, imp, size, cont])]
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete_certificat(self, certificat, cont):
|
def delete_certificat(self, certificat, cont):
|
||||||
|
@ -1068,6 +1199,133 @@ les valeurs valident sont :
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_csr(self, certificat, cont):
|
||||||
|
def box(text):
|
||||||
|
fp, path = tempfile.mkstemp()
|
||||||
|
os.write(fp, text)
|
||||||
|
os.close(fp)
|
||||||
|
self.dialog.textbox(filename=path, height=0, width=0,
|
||||||
|
backtitle="Appuyez sur CTRL+MAJ+V pour coller",
|
||||||
|
title="Récupération d'un certificat",
|
||||||
|
no_mouse=True,)
|
||||||
|
os.remove(path)
|
||||||
|
return
|
||||||
|
|
||||||
|
def todo(certificat, self_cont, cont):
|
||||||
|
if certificat['encrypted']:
|
||||||
|
if "machineCrans" in certificat.machine()["objectClass"]:
|
||||||
|
passphrase = secrets.get('privatekey_passphrase')
|
||||||
|
else:
|
||||||
|
self.dialog.msgbox("Mercie de fournir le mot de passe chiffrant la clef privée.\nIl a été choisis lors de la création de la clef.",
|
||||||
|
title="Génération d'un CSR",
|
||||||
|
width=70,
|
||||||
|
height=10)
|
||||||
|
passphrase = self.get_password(cont, confirm=False)
|
||||||
|
else:
|
||||||
|
passphrase = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
if passphrase:
|
||||||
|
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, str(certificat['privatekey'][0]), passphrase)
|
||||||
|
else:
|
||||||
|
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, str(certificat['privatekey'][0]))
|
||||||
|
except crypto.Error as e:
|
||||||
|
if len(e.message) > 2 and len(e.message[2]) > 2 and e.message[2][2] == 'bad password read':
|
||||||
|
self.dialog.msgbox("Mauvais mot de passe")
|
||||||
|
raise Continue(self_cont)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
req = createCertRequest(pkey,
|
||||||
|
digest="sha1",
|
||||||
|
subjectAltName=[str(host) for host in certificat['hostCert'][1:]],
|
||||||
|
C=u"FR",
|
||||||
|
ST=u"Ile de France",
|
||||||
|
L=u"Cachan",
|
||||||
|
O=u"Association Cachan Réseaux A Normal SUP (C.R.A.N.S)",
|
||||||
|
OU=u"Crans",
|
||||||
|
CN=unicode(certificat['hostCert'][0]),
|
||||||
|
)
|
||||||
|
csr = crypto.dump_certificate_request(crypto.FILETYPE_PEM, req)
|
||||||
|
with self.conn.search(dn=certificat.dn, scope=0, mode='rw')[0] as certificat:
|
||||||
|
certificat['csr']=unicode(csr)
|
||||||
|
certificat.save()
|
||||||
|
self.handle_dialog(cont, box, csr)
|
||||||
|
if self.dialog.yesno("Remplacer le certificat actuel ?") == self.dialog.DIALOG_OK:
|
||||||
|
return self.create_certificat(certificat=certificat, cont=cont(certificat=certificat))
|
||||||
|
else:
|
||||||
|
raise Continue(cont(certificat=certificat))
|
||||||
|
|
||||||
|
self_cont = TailCall(self.gen_csr, certificat=certificat, cont=cont)
|
||||||
|
return self.handle_dialog_result(
|
||||||
|
code=self.dialog.DIALOG_OK,
|
||||||
|
output="",
|
||||||
|
cancel_cont=cont,
|
||||||
|
error_cont=self_cont,
|
||||||
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [certificat, self_cont, cont])]
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_certificat(self, certificat, cont, privatekey=False, csr=False):
|
||||||
|
def box(text):
|
||||||
|
fp, path = tempfile.mkstemp()
|
||||||
|
os.write(fp, text)
|
||||||
|
os.close(fp)
|
||||||
|
self.dialog.textbox(filename=path, height=0, width=0,
|
||||||
|
backtitle="Appuyez sur CTRL+MAJ+V pour coller",
|
||||||
|
title="Récupération d'un certificat",
|
||||||
|
no_mouse=True,)
|
||||||
|
os.remove(path)
|
||||||
|
return
|
||||||
|
if privatekey:
|
||||||
|
self.handle_dialog(cont, box, unicode(certificat['privatekey'][0]))
|
||||||
|
elif csr:
|
||||||
|
self.handle_dialog(cont, box, unicode(certificat['csr'][0]))
|
||||||
|
else:
|
||||||
|
self.handle_dialog(cont, box, unicode(ssl.DER_cert_to_PEM_cert(str(certificat['certificat'][0]))))
|
||||||
|
raise Continue(cont)
|
||||||
|
|
||||||
|
def create_csr(self, cont, machine=None, certificat=None):
|
||||||
|
"""Permet d'ajouter un csr à une machine à partir du PEM du csr"""
|
||||||
|
if machine is None and certificat is None:
|
||||||
|
raise EnvironmentError("Il faut fournir au moins une machine ou un certificat")
|
||||||
|
# input multiline en utilisant un editbox
|
||||||
|
def box():
|
||||||
|
fp, path = tempfile.mkstemp()
|
||||||
|
os.close(fp)
|
||||||
|
cmd = ['--editbox', path, "0", "0"]
|
||||||
|
(code, output) = self.dialog._perform(*(cmd,),
|
||||||
|
no_mouse=True, # On désactive la sourie sinon dialog segfault si on clic
|
||||||
|
backtitle="Appuyez sur CTRL+MAJ+V pour coller",
|
||||||
|
timeout=self.timeout,
|
||||||
|
title="Création d'un certificat, entrez le PEM du certificat")
|
||||||
|
os.remove(path)
|
||||||
|
if code == self.dialog.DIALOG_OK:
|
||||||
|
return code, output
|
||||||
|
else:
|
||||||
|
return code, None
|
||||||
|
|
||||||
|
def todo(machine, certificat, pem, cont):
|
||||||
|
if certificat:
|
||||||
|
with self.conn.search(dn=certificat.dn, scope=0, mode='rw')[0] as certificat:
|
||||||
|
certificat['csr'] = unicode(pem, 'utf-8')
|
||||||
|
certificat.save()
|
||||||
|
else:
|
||||||
|
with self.conn.newCertificat(machine.dn, {}) as certificat:
|
||||||
|
certificat['hostCert']=unicode(machine['host'][0])
|
||||||
|
certificat['csr'] = unicode(pem, 'utf-8')
|
||||||
|
certificat.create()
|
||||||
|
raise Continue(cont(certificat=certificat, machine=certificat.machine()))
|
||||||
|
|
||||||
|
(code, pem) = self.handle_dialog(cont, box)
|
||||||
|
self_cont = TailCall(self.create_csr, machine=machine, certificat=certificat, cont=cont)
|
||||||
|
return self.handle_dialog_result(
|
||||||
|
code=code,
|
||||||
|
output=pem,
|
||||||
|
cancel_cont=cont,
|
||||||
|
error_cont=self_cont,
|
||||||
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [machine, certificat, pem, cont])]
|
||||||
|
)
|
||||||
|
|
||||||
def modif_machine_certificat(self, machine, cont, tag=None, certificat=None):
|
def modif_machine_certificat(self, machine, cont, tag=None, certificat=None):
|
||||||
"""Permet l'édition d'un certificat d'une machine"""
|
"""Permet l'édition d'un certificat d'une machine"""
|
||||||
self_cont = TailCall(self.modif_machine_certificat, machine=machine, cont=cont, certificat=certificat)
|
self_cont = TailCall(self.modif_machine_certificat, machine=machine, cont=cont, certificat=certificat)
|
||||||
|
@ -1075,33 +1333,69 @@ les valeurs valident sont :
|
||||||
certificat_index = self.edit_certificat_select(machine=machine, title="Modification des certificats de %s" % machine['host'][0], cont=cont)
|
certificat_index = self.edit_certificat_select(machine=machine, title="Modification des certificats de %s" % machine['host'][0], cont=cont)
|
||||||
if certificat_index == 'new':
|
if certificat_index == 'new':
|
||||||
raise Continue(TailCall(self.create_certificat, machine=machine, cont=self_cont))
|
raise Continue(TailCall(self.create_certificat, machine=machine, cont=self_cont))
|
||||||
|
elif certificat_index == 'priv':
|
||||||
|
raise Continue(TailCall(self.create_privatekey, machine=machine, cont=self_cont))
|
||||||
|
elif certificat_index == 'csr':
|
||||||
|
raise Continue(TailCall(self.create_csr, machine=machine, cont=self_cont))
|
||||||
certificat = machine.certificats()[certificat_index]
|
certificat = machine.certificats()[certificat_index]
|
||||||
menu = {
|
menu = {
|
||||||
'Hostname' : {'text':"Noms d'hôte utilisant le certificat", "attribut":attributs.hostCert},
|
'Hostname' : {'text':"Noms d'hôte utilisant le certificat", "help":'Il doivent être inclus dans les host et hostAlias de la machine parente', "attribut":attributs.hostCert},
|
||||||
'TLSA' : {'text':"Paramètres pour les champs dns TLSA", "callback":self.certificat_tlsa},
|
'AddPrivateKey' : {'text': 'Ajouter la clef privée', 'help':'La clef doit être obligatoirement chiffrée avant envoi', "callback":TailCall(self.create_privatekey, imp=True)},
|
||||||
'Autre': {'text' : "Modifier les attribut booléen comme revocked", "callback":self.modif_certificat_boolean},
|
'AddCertificate' : {'text': 'Ajouter un certificat X509', 'help':'', "callback":self.create_certificat},
|
||||||
'Supprimer' : {'text' : "Supprimer le certificat", "callback":self.delete_certificat},
|
'SetCertificate' : {'text': 'Remplacer le certificat X509', 'help':'', "callback":self.create_certificat},
|
||||||
|
'TLSA' : {'text':"Paramètres pour les champs dns TLSA", 'help':'Permet de configurer DANE pour le certificat X509', "callback":self.certificat_tlsa},
|
||||||
|
'Autre': {'text' : "Modifier les attribut booléen comme revocked", 'help':'', "callback":self.modif_certificat_boolean},
|
||||||
|
'GetPriv' : {'text' : 'Récupérer la clef privée', 'help':"Affiche la clef privée telle qu'elle est dans la base de donnée, c'est à dire chiffrée", 'callback':TailCall(self.get_certificat, privatekey=True)},
|
||||||
|
'GetCert' : {'text' : 'Récupérer le certificat', 'help':"Affiche le certificat au format PEM", 'callback':self.get_certificat},
|
||||||
|
'GetCSR' : {'text' : 'Récupérer la requête de signature de certificat', 'help':"Affiche le CSR au format PEM", 'callback':TailCall(self.get_certificat, csr=True)},
|
||||||
|
'GenCSR' : {'text' : 'Générer un CSR, puis remplacer le certificat', 'help':'Généré à partir de la clef privée. Les noms (CN et subjectAltName) sont pris à partir de Hostname (attribut hostCert)', "callback":self.gen_csr},
|
||||||
|
'Remarque' : {'text': 'Mettre des remarques', 'help':'La première apparait dans la liste des certificats', 'attribut':attributs.info},
|
||||||
|
'Supprimer' : {'text' : "Supprimer le certificat", 'help':'', "callback":self.delete_certificat},
|
||||||
}
|
}
|
||||||
menu_order = ['Hostname', 'TLSA', 'Autre', 'Supprimer']
|
if "privateKey" in certificat["objectClass"]:
|
||||||
|
menu
|
||||||
|
menu_order = ['Hostname']
|
||||||
|
if not "privateKey" in certificat['objectClass']:
|
||||||
|
menu_order.append('AddPrivateKey')
|
||||||
|
if not "x509Cert" in certificat['objectClass']:
|
||||||
|
menu_order.extend([ 'AddCertificate'])
|
||||||
|
if "x509Cert" in certificat['objectClass']:
|
||||||
|
menu_order.extend(['TLSA', 'Autre', 'GetCert'])
|
||||||
|
if certificat['csr']:
|
||||||
|
menu_order.extend(['GetCSR'])
|
||||||
|
if "privateKey" in certificat['objectClass']:
|
||||||
|
if attributs.nounou in self.conn.droits or machine.dn.startswith(self.conn.dn):
|
||||||
|
menu_order.extend(['GetPriv'])
|
||||||
|
menu_order.extend(['GenCSR'])
|
||||||
|
menu_order.extend(['Remarque', 'Supprimer'])
|
||||||
def box(default_item=None):
|
def box(default_item=None):
|
||||||
|
text="Certificat de %s, xid=%s :\n" % (certificat['hostCert'][0], certificat['xid'][0])
|
||||||
|
if "x509Cert" in certificat['objectClass']:
|
||||||
|
text += " * Certificat N°0x%X émis par %s, valable du %s au %s\n" % (
|
||||||
|
int(str(certificat['serialNumber'][0])),
|
||||||
|
certificat['issuerCN'][0],
|
||||||
|
time.strftime("%d/%m/%Y", time.localtime(int(certificat['start'][0]))),
|
||||||
|
time.strftime("%d/%m/%Y", time.localtime(int(certificat['end'][0])))
|
||||||
|
)
|
||||||
|
if "privateKey" in certificat['objectClass']:
|
||||||
|
text += " * Clef privée\n"
|
||||||
|
if certificat['csr']:
|
||||||
|
text += " * Requête de signature de certificat\n"
|
||||||
|
if certificat['info']:
|
||||||
|
text += str(certificat['info'][0])
|
||||||
return self.dialog.menu(
|
return self.dialog.menu(
|
||||||
"Paramètres pour le certificat N°0x%X émis par %s, valable du %s au %s" % (
|
text,
|
||||||
int(str(certificat['serialNumber'][0])),
|
|
||||||
certificat['issuerCN'][0],
|
|
||||||
time.strftime("%d/%m/%Y", time.localtime(int(certificat['start'][0]))),
|
|
||||||
time.strftime("%d/%m/%Y", time.localtime(int(certificat['end'][0])))
|
|
||||||
),
|
|
||||||
width=0,
|
width=0,
|
||||||
height=0,
|
height=0,
|
||||||
menu_height=0,
|
menu_height=0,
|
||||||
item_help=0,
|
item_help=1,
|
||||||
timeout=self.timeout,
|
timeout=self.timeout,
|
||||||
default_item=str(default_item),
|
default_item=str(default_item),
|
||||||
title="Modification des certificats de %s" % certificat.machine()['host'][0],
|
title="Modification des certificats de %s" % certificat.machine()['host'][0],
|
||||||
scrollbar=True,
|
scrollbar=True,
|
||||||
cancel_label="Retour",
|
cancel_label="Retour",
|
||||||
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
||||||
choices=[(key, menu[key]['text']) for key in menu_order])
|
choices=[(key, menu[key]['text'], menu[key]['help']) for key in menu_order])
|
||||||
|
|
||||||
def todo(tag, menu, certificat, self_cont):
|
def todo(tag, menu, certificat, self_cont):
|
||||||
if not tag in menu_order:
|
if not tag in menu_order:
|
||||||
|
@ -1113,8 +1407,8 @@ les valeurs valident sont :
|
||||||
raise Continue(TailCall(self.modif_certificat_attributs, certificat=certificat, cont=self_cont(certificat=certificat, tag=tag), attr=menu[tag]['attribut'].ldap_name))
|
raise Continue(TailCall(self.modif_certificat_attributs, certificat=certificat, cont=self_cont(certificat=certificat, tag=tag), attr=menu[tag]['attribut'].ldap_name))
|
||||||
else:
|
else:
|
||||||
raise EnvironmentError("Il n'y a ni champ 'attribut' ni 'callback' pour le tag %s" % tag)
|
raise EnvironmentError("Il n'y a ni champ 'attribut' ni 'callback' pour le tag %s" % tag)
|
||||||
(code, tag) = box(tag)
|
(code, tag) = self.handle_dialog(cont, box, tag)
|
||||||
cancel_cont = cont(machine=machine) if certificat is None else self_cont(certificat=None)
|
cancel_cont = cont(machine=machine) if certificat is None else self_cont(machine=certificat.machine(), certificat=None)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
output=tag,
|
output=tag,
|
||||||
|
@ -1129,8 +1423,18 @@ les valeurs valident sont :
|
||||||
def box(default_item=None):
|
def box(default_item=None):
|
||||||
index=0
|
index=0
|
||||||
choices = [('new', 'Ajouter un nouveau certificat')]
|
choices = [('new', 'Ajouter un nouveau certificat')]
|
||||||
|
choices.append(('priv', 'Générer une nouvelle clef privée'))
|
||||||
|
choices.append(('csr', 'Ajouter une nouvelle requête de certificat'))
|
||||||
for cert in machine.certificats():
|
for cert in machine.certificats():
|
||||||
choices.append((str(index), "Emit par %s pour %s du %s au %s" % (cert['issuerCN'][0], ', '.join(str(cn) for cn in cert['hostCert']), time.strftime("%d/%m/%Y", time.localtime(int(cert['start'][0]))), time.strftime("%d/%m/%Y", time.localtime(int(cert['end'][0]))))))
|
if cert['info']:
|
||||||
|
item = str(cert['info'][0])
|
||||||
|
elif "x509Cert" in cert['objectClass']:
|
||||||
|
item = "Emit par %s pour %s du %s au %s" % (cert['issuerCN'][0], ', '.join(str(cn) for cn in cert['hostCert']), time.strftime("%d/%m/%Y", time.localtime(int(cert['start'][0]))), time.strftime("%d/%m/%Y", time.localtime(int(cert['end'][0]))))
|
||||||
|
elif "privateKey" in cert['objectClass']:
|
||||||
|
item = "Clef privée de %s, xid=%s" % (cert['hostCert'][0], cert['xid'][0])
|
||||||
|
elif cert['csr']:
|
||||||
|
item = "Requête de signature de certificat pour %s, xid=%s" % (cert['hostCert'][0], cert['xid'][0])
|
||||||
|
choices.append((str(index), item))
|
||||||
index+=1
|
index+=1
|
||||||
return self.dialog.menu(
|
return self.dialog.menu(
|
||||||
"Modifier ou ajouter un certificat ?",
|
"Modifier ou ajouter un certificat ?",
|
||||||
|
@ -1147,17 +1451,17 @@ les valeurs valident sont :
|
||||||
choices=choices)
|
choices=choices)
|
||||||
|
|
||||||
def todo(tag):
|
def todo(tag):
|
||||||
if tag == 'new':
|
if tag in ['new', 'priv', 'csr']:
|
||||||
return tag
|
return tag
|
||||||
else:
|
else:
|
||||||
return int(tag)
|
return int(tag)
|
||||||
|
|
||||||
(code, tag) = box()
|
(code, tag) = self.handle_dialog(cont, box)
|
||||||
retry_cont = TailCall(self.edit_certificat_select, machine=machine, title=title, cont=cont)
|
retry_cont = TailCall(self.edit_certificat_select, machine=machine, title=title, cont=cont)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
output=tag,
|
output=tag,
|
||||||
cancel_cont=cont,
|
cancel_cont=cont(machine=machine),
|
||||||
error_cont=retry_cont,
|
error_cont=retry_cont,
|
||||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [tag])]
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [tag])]
|
||||||
)
|
)
|
||||||
|
@ -1241,7 +1545,7 @@ les valeurs valident sont :
|
||||||
else:
|
else:
|
||||||
raise EnvironmentError("Il n'y a ni champ 'attribut' ni 'callback' pour le tag %s" % tag)
|
raise EnvironmentError("Il n'y a ni champ 'attribut' ni 'callback' pour le tag %s" % tag)
|
||||||
|
|
||||||
(code, tag) = box(tag)
|
(code, tag) = self.handle_dialog(cont, box, tag)
|
||||||
cont_ret = TailCall(self.modif_machine, cont=cont, machine=machine, tag=tag)
|
cont_ret = TailCall(self.modif_machine, cont=cont, machine=machine, tag=tag)
|
||||||
|
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
|
@ -1280,19 +1584,19 @@ les valeurs valident sont :
|
||||||
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
||||||
choices=[(key, menu[key]['text']) for key in menu_order])
|
choices=[(key, menu[key]['text']) for key in menu_order])
|
||||||
|
|
||||||
def todo(tag, menu, proprio, self_cont):
|
def todo(tag, menu, proprio, self_cont, cont):
|
||||||
if not tag in menu_order:
|
if not tag in menu_order:
|
||||||
raise Continue(self_cont)
|
raise Continue(self_cont)
|
||||||
else:
|
else:
|
||||||
return self.machine_information(
|
return self.machine_information(
|
||||||
cont=self_cont,
|
cont=cont,
|
||||||
machine=None,
|
machine=None,
|
||||||
objectClass=menu[tag]['objectClass'],
|
objectClass=menu[tag]['objectClass'],
|
||||||
proprio=proprio,
|
proprio=proprio,
|
||||||
realm=menu[tag]['realm']
|
realm=menu[tag]['realm']
|
||||||
)
|
)
|
||||||
|
|
||||||
(code, tag) = box(tag)
|
(code, tag) = self.handle_dialog(cont, box, tag)
|
||||||
cont = cont(proprio=None) if isinstance(proprio, objets.AssociationCrans) else cont(proprio=proprio)
|
cont = cont(proprio=None) if isinstance(proprio, objets.AssociationCrans) else cont(proprio=proprio)
|
||||||
self_cont = TailCall(self.create_machine_proprio, cont=cont, proprio=proprio, tag=tag)
|
self_cont = TailCall(self.create_machine_proprio, cont=cont, proprio=proprio, tag=tag)
|
||||||
|
|
||||||
|
@ -1301,7 +1605,7 @@ les valeurs valident sont :
|
||||||
output=tag,
|
output=tag,
|
||||||
cancel_cont=cont,
|
cancel_cont=cont,
|
||||||
error_cont=self_cont,
|
error_cont=self_cont,
|
||||||
codes_todo=[([self.dialog.DIALOG_OK], todo, [tag, menu, proprio, self_cont])]
|
codes_todo=[([self.dialog.DIALOG_OK], todo, [tag, menu, proprio, self_cont, cont])]
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_machine_adherent(self, cont, adherent=None):
|
def create_machine_adherent(self, cont, adherent=None):
|
||||||
|
@ -1384,7 +1688,7 @@ les valeurs valident sont :
|
||||||
else:
|
else:
|
||||||
raise EnvironmentError("Il n'y a ni champ 'attribut' ni 'callback' pour le tag %s" % tag)
|
raise EnvironmentError("Il n'y a ni champ 'attribut' ni 'callback' pour le tag %s" % tag)
|
||||||
|
|
||||||
(code, tag) = box(tag)
|
(code, tag) = self.handle_dialog(cont, box, tag)
|
||||||
cont_ret = TailCall(self.modif_adherent, cont=cont, adherent=adherent, tag=tag)
|
cont_ret = TailCall(self.modif_adherent, cont=cont, adherent=adherent, tag=tag)
|
||||||
|
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
|
@ -1492,7 +1796,7 @@ les valeurs valident sont :
|
||||||
raise Continue(cont(adherent=adherent))
|
raise Continue(cont(adherent=adherent))
|
||||||
|
|
||||||
|
|
||||||
(code, tags, make_compte_crans) = box(make_compte_crans)
|
(code, tags, make_compte_crans) = self.handle_dialog(cont, box, make_compte_crans)
|
||||||
|
|
||||||
# On prépare les fiels à afficher à l'utilisateur si une erreure à lieu
|
# On prépare les fiels à afficher à l'utilisateur si une erreure à lieu
|
||||||
# pendant le traitement des donnée (on n'éfface pas ce qui a déjà été entré
|
# pendant le traitement des donnée (on n'éfface pas ce qui a déjà été entré
|
||||||
|
@ -1563,7 +1867,7 @@ les valeurs valident sont :
|
||||||
self.display_item(item=adherent, title="Adhérent déménagé dans la chambre %s" % output)
|
self.display_item(item=adherent, title="Adhérent déménagé dans la chambre %s" % output)
|
||||||
raise Continue(success_cont(adherent=adherent))
|
raise Continue(success_cont(adherent=adherent))
|
||||||
|
|
||||||
(code, output) = box()
|
(code, output) = self.handle_dialog(cont, box)
|
||||||
self_cont = TailCall(self.adherent_chambre_campus, adherent=adherent, success_cont=success_cont, cont=cont)
|
self_cont = TailCall(self.adherent_chambre_campus, adherent=adherent, success_cont=success_cont, cont=cont)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -1658,7 +1962,7 @@ les valeurs valident sont :
|
||||||
else:
|
else:
|
||||||
raise EnvironmentError("Impossible, on a fait tous les cas, python est buggué")
|
raise EnvironmentError("Impossible, on a fait tous les cas, python est buggué")
|
||||||
|
|
||||||
(code, output) = box()
|
(code, output) = self.handle_dialog(cont, box)
|
||||||
self_cont = TailCall(self.adherent_chambre_ext, adherent=adherent, keep_machine=keep_machine, keep_compte=keep_compte, success_cont=success_cont, cont=cont)
|
self_cont = TailCall(self.adherent_chambre_ext, adherent=adherent, keep_machine=keep_machine, keep_compte=keep_compte, success_cont=success_cont, cont=cont)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -1697,7 +2001,7 @@ les valeurs valident sont :
|
||||||
else:
|
else:
|
||||||
raise Continue(TailCall(menu[tag]['callback'], cont=self_cont, success_cont=cont, adherent=adherent))
|
raise Continue(TailCall(menu[tag]['callback'], cont=self_cont, success_cont=cont, adherent=adherent))
|
||||||
|
|
||||||
(code, tag) = box(default_item)
|
(code, tag) = self.handle_dialog(cont, box, default_item)
|
||||||
self_cont = TailCall(self.adherent_chambre, adherent=adherent, cont=cont, default_item=tag)
|
self_cont = TailCall(self.adherent_chambre, adherent=adherent, cont=cont, default_item=tag)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -1808,7 +2112,7 @@ les valeurs valident sont :
|
||||||
title="Choix du mot de passe pour %s %s" % (proprio.get('prenom', [''])[0], proprio["nom"][0]),
|
title="Choix du mot de passe pour %s %s" % (proprio.get('prenom', [''])[0], proprio["nom"][0]),
|
||||||
)
|
)
|
||||||
raise Continue(cont(proprio=proprio))
|
raise Continue(cont(proprio=proprio))
|
||||||
(code, passwords) = box()
|
(code, passwords) = self.handle_dialog(cont, box)
|
||||||
self_cont = TailCall(self.proprio_compte_password, proprio=proprio, cont=cont)
|
self_cont = TailCall(self.proprio_compte_password, proprio=proprio, cont=cont)
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -1911,7 +2215,7 @@ les valeurs valident sont :
|
||||||
else:
|
else:
|
||||||
raise Continue(TailCall(menu[tag]['callback'], cont=self_cont, proprio=proprio))
|
raise Continue(TailCall(menu[tag]['callback'], cont=self_cont, proprio=proprio))
|
||||||
|
|
||||||
(code, tag) = box(default_item)
|
(code, tag) = self.handle_dialog(cont, box, default_item)
|
||||||
self_cont = TailCall(self.proprio_compte, proprio=proprio, cont=cont, default_item=tag_translate[tag])
|
self_cont = TailCall(self.proprio_compte, proprio=proprio, cont=cont, default_item=tag_translate[tag])
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -1956,7 +2260,7 @@ les valeurs valident sont :
|
||||||
self.check_ldap()
|
self.check_ldap()
|
||||||
raise Continue(cont(adherent=adherent))
|
raise Continue(cont(adherent=adherent))
|
||||||
|
|
||||||
(code, droits) = box()
|
(code, droits) = self.handle_dialog(cont, box)
|
||||||
self_cont = TailCall(self.adherent_droits, adherent=adherent, cont=cont, choices_values=[(d, "", 1 if d in droits else 0) for d in attributs.TOUS_DROITS])
|
self_cont = TailCall(self.adherent_droits, adherent=adherent, cont=cont, choices_values=[(d, "", 1 if d in droits else 0) for d in attributs.TOUS_DROITS])
|
||||||
return self.handle_dialog_result(
|
return self.handle_dialog_result(
|
||||||
code=code,
|
code=code,
|
||||||
|
@ -2112,12 +2416,13 @@ les valeurs valident sont :
|
||||||
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login,
|
||||||
choices=[(key, menu.get(key, menu[''])['text'], menu.get(key, menu['']).get('help', "")) for key in menu_order])
|
choices=[(key, menu.get(key, menu[''])['text'], menu.get(key, menu['']).get('help', "")) for key in menu_order])
|
||||||
|
|
||||||
(code, tag) = box(tag)
|
self_cont = TailCall(self.menu_principal, tag=tag, proprio=proprio, machine=machine)
|
||||||
|
(code, tag) = self.handle_dialog(TailCall(handle_exit_code, self.dialog, self.dialog.DIALOG_ESC), box, tag)
|
||||||
callback = menu.get(tag, menu[''])['callback']
|
callback = menu.get(tag, menu[''])['callback']
|
||||||
if handle_exit_code(self.dialog, code) and callback:
|
if handle_exit_code(self.dialog, code) and callback:
|
||||||
return TailCall(callback, cont=TailCall(self.menu_principal, tag=tag, machine=machine, proprio=proprio))
|
return TailCall(callback, cont=TailCall(self.menu_principal, tag=tag, machine=machine, proprio=proprio))
|
||||||
else:
|
else:
|
||||||
return TailCall(self.menu_principal, tag=tag, proprio=proprio, machine=machine)
|
return self_cont
|
||||||
|
|
||||||
def main(gc, cont=None):
|
def main(gc, cont=None):
|
||||||
while True:
|
while True:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue