638 lines
24 KiB
Python
638 lines
24 KiB
Python
# -*- coding: utf-8 -*-
|
|
###########################################################################
|
|
#
|
|
# Eole NG - 2007
|
|
# Copyright Pole de Competence Eole (Ministere Education - Academie Dijon)
|
|
# Licence CeCill cf /root/LicenceEole.txt
|
|
# eole@ac-dijon.fr
|
|
#
|
|
# libsecure.py
|
|
#
|
|
# classes utilitaires pour lancement des services en https
|
|
#
|
|
###########################################################################
|
|
"""
|
|
points d'entrée de l'api
|
|
|
|
- gen_certif -> génère **un** certif
|
|
- gen_certs -> génère tous les certifs
|
|
|
|
cf creole/doc/certifs.txt
|
|
|
|
"""
|
|
# certains imports sont utilisés dans les fragments de code installés
|
|
# dans /usr/share/eole/certs
|
|
from os.path import join, splitext, basename, dirname, isdir, isfile, islink, exists, realpath
|
|
from os import unlink, symlink, stat
|
|
import os, glob, time
|
|
from shutil import copy
|
|
from subprocess import Popen, PIPE
|
|
from OpenSSL import SSL
|
|
import re
|
|
|
|
from .i18n import _
|
|
|
|
# chemin du certificat eole par défaut
|
|
from .config import cert_file, key_file, SSL_LAST_FILE
|
|
from .client import CreoleClient
|
|
from pyeole.process import system_out, system_code
|
|
|
|
client = CreoleClient()
|
|
|
|
global regexp_get_subject
|
|
regexp_get_subject = None
|
|
|
|
def prep_dir() :
|
|
"""
|
|
Création de l'arborescence pour openssl
|
|
"""
|
|
#on génère le random
|
|
load_default_conf_if_needed()
|
|
rand_file = os.path.join(ssl_dir, ".rand")
|
|
if not os.path.isfile(rand_file) :
|
|
cmd_random = "/bin/dd if=/dev/urandom of=%s bs=1k count=16 >/dev/null 2>&1" % (rand_file)
|
|
cmd = Popen(cmd_random, shell=True)
|
|
res = cmd.wait()
|
|
if res != 0:
|
|
raise Exception(_(u"! Error while generating entropy file !"))
|
|
#on crée les fichiers pour gerer la pki
|
|
file_serial = os.path.join(ssl_dir, "serial")
|
|
if not os.path.isfile(file_serial) :
|
|
f = file(file_serial, "w")
|
|
f.write(str(start_index))
|
|
f.close()
|
|
file_index = os.path.join(ssl_dir, "index.txt")
|
|
if not os.path.isfile(file_index) :
|
|
f = file(file_index, "w")
|
|
f.close()
|
|
newcerts = os.path.join(ssl_dir, "newcerts")
|
|
if not os.path.isdir(newcerts):
|
|
os.makedirs(newcerts)
|
|
if not os.path.isdir(key_dir):
|
|
os.makedirs(key_dir)
|
|
if not os.path.isdir(cert_dir):
|
|
os.makedirs(cert_dir)
|
|
if not os.path.isdir(req_dir):
|
|
os.makedirs(req_dir)
|
|
if not os.path.isdir(local_ca_dir):
|
|
os.makedirs(local_ca_dir)
|
|
##cmd = Popen("chmod 611 %s" % (key_dir), shell=True)
|
|
dhfile = os.path.join(ssl_dir, "dh")
|
|
if not os.path.isfile(dhfile):
|
|
gen_dh = '/usr/bin/openssl dhparam -out "%s" 1024 >/dev/null 2>&1' % (dhfile)
|
|
Popen(gen_dh, shell=True)
|
|
|
|
def sup_passwd(tmp_keyfile, keyfile) :
|
|
"""
|
|
Supression de la passphrase sur la clef privée
|
|
"""
|
|
load_default_conf_if_needed()
|
|
key_cmd = '/usr/bin/openssl rsa -in "%s" -passin pass:secret -out "%s" >/dev/null 2>&1' % (tmp_keyfile, keyfile)
|
|
cmd = Popen(key_cmd, shell=True)
|
|
res = cmd.wait()
|
|
if res != 0:
|
|
raise Exception(_(u'! Error while generating ssl key in {0} !').format(keyfile))
|
|
|
|
def finalise_cert (certfile, keyfile, key_user='', key_grp='', key_chmod='',
|
|
cert_user='', cert_grp='', cert_chmod=''):
|
|
"""
|
|
Finalisation du certif
|
|
"""
|
|
load_default_conf_if_needed()
|
|
if key_user != '':
|
|
try:
|
|
res = Popen("chown %s %s" % (key_user, keyfile), shell=True).wait()
|
|
assert res == 0
|
|
except:
|
|
print _(u"\n! Rights on {0} can't be modified").format(keyfile)
|
|
return False
|
|
if key_grp != '':
|
|
try:
|
|
res=Popen("/bin/chgrp %s %s" % (key_grp, keyfile), shell=True).wait()
|
|
assert res == 0
|
|
except:
|
|
print _(u"\n! Rights on {0} can't be modified").format(keyfile)
|
|
return False
|
|
if key_chmod != '':
|
|
try:
|
|
res = Popen("/bin/chmod %s %s" % (key_chmod, keyfile), shell=True).wait()
|
|
assert res == 0
|
|
except:
|
|
print _(u"\n! Rights on {0} can't be modified").format(keyfile)
|
|
return False
|
|
if cert_user != '':
|
|
try:
|
|
res = Popen("/bin/chown %s %s" % (cert_user, certfile), shell=True).wait()
|
|
assert res == 0
|
|
except:
|
|
print _(u"\n! Rights on {0} can't be modified").format(certfile)
|
|
return False
|
|
if cert_grp != '':
|
|
try:
|
|
res = Popen("/bin/chgrp %s %s" % (cert_grp, certfile), shell=True).wait()
|
|
assert res == 0
|
|
except:
|
|
print _(u"\n! Rights on {0} can't be modified").format(certfile)
|
|
return False
|
|
if cert_chmod != '':
|
|
try:
|
|
res = Popen("/bin/chmod %s %s" % (cert_chmod, certfile), shell=True).wait()
|
|
assert res == 0
|
|
except:
|
|
print _(u"\n! Rights on {0} can't be modified").format(certfile)
|
|
return False
|
|
return True
|
|
|
|
|
|
def is_simple_cert(cert_file):
|
|
"""
|
|
Teste si le fichier contient un simple certificat ou une chaîne.
|
|
:param cert_file: chemin du fichier à tester
|
|
:type cert_file: str
|
|
"""
|
|
with open(cert_file, 'r') as pem:
|
|
cert_num = len(re.findall(r'-+BEGIN CERTIFICATE-+', pem.read()))
|
|
return cert_num == 1
|
|
|
|
def get_certs_catalog(simple=True):
|
|
"""
|
|
Créer un dictionnaire des certificats présents
|
|
pour accélérer la reconstitution de la chaîne
|
|
de certificats intermédiaires.
|
|
:param simple: filtre sur les certificats à référencer
|
|
:type simple: booléen
|
|
"""
|
|
global certs_catalog
|
|
certs_catalog = {}
|
|
for cert_file in glob.glob(os.path.join(ssl_dir, 'certs/*')):
|
|
try:
|
|
if simple and is_simple_cert(cert_file):
|
|
certs_catalog[get_subject(certfile=cert_file)] = cert_file
|
|
elif not simple:
|
|
certs_catalog[get_subject(certfile=cert_file)] = cert_file
|
|
except:
|
|
continue
|
|
return certs_catalog
|
|
|
|
|
|
def get_certs_chain(certs):
|
|
"""
|
|
Récupération de la chaîne de certificats
|
|
:param certs: liste des certificats dans l'ordre de la chaîne.
|
|
:type certs: liste de chemins
|
|
"""
|
|
global certs_catalog, ca_issuer
|
|
load_default_conf_if_needed()
|
|
subject = get_subject(certfile=certs[-1])
|
|
issuer = get_issuer_subject(certfile=certs[-1])
|
|
if ca_issuer is None:
|
|
ca_issuer = get_issuer_subject(certfile=ca_file)
|
|
if subject == issuer:
|
|
pass
|
|
elif issuer == ca_issuer:
|
|
certs.append(ca_file)
|
|
else:
|
|
try:
|
|
if certs_catalog is None:
|
|
certs_catalog = get_certs_catalog()
|
|
certs.append(certs_catalog[issuer])
|
|
get_certs_chain(certs)
|
|
except KeyError as e:
|
|
print _(u"Certificate chain incomplete.")
|
|
return certs
|
|
|
|
|
|
def get_intermediate_certs(cert):
|
|
"""
|
|
Récupération de la liste des certificats intermédiaires.
|
|
:param cert: chemin du certificat pour lequel on reconstitue la chaîne
|
|
:type cert:
|
|
"""
|
|
load_default_conf_if_needed()
|
|
try:
|
|
chain = get_certs_chain([cert,])[1:-1]
|
|
except:
|
|
chain = []
|
|
return chain
|
|
|
|
|
|
def concat_fic(dst_fic, in_fics, overwrite=False, need_link=True):
|
|
"""
|
|
Concaténation d'une liste de fichiers dans un fichier de destination
|
|
(le contenu d'origine est conservé)
|
|
"""
|
|
load_default_conf_if_needed()
|
|
if need_link:
|
|
remove_link(dst_fic)
|
|
if type(in_fics) != list:
|
|
in_fics = [in_fics]
|
|
for fic in in_fics:
|
|
if not os.path.isfile(fic):
|
|
print _(u"Error: file {0} does not exist").format(fic)
|
|
data = ""
|
|
for fic_src in in_fics:
|
|
f_src = file(fic_src)
|
|
data += f_src.read().rstrip() + '\n'
|
|
f_src.close()
|
|
if overwrite:
|
|
f_dst = file(dst_fic, "w")
|
|
else:
|
|
f_dst = file(dst_fic, "a+")
|
|
f_dst.write(data)
|
|
f_dst.close()
|
|
if need_link:
|
|
build_link(dst_fic, in_fics)
|
|
|
|
def gen_certs(regen=False, merge=True):
|
|
"""
|
|
Génère la ca puis les certificats
|
|
"""
|
|
load_default_conf_if_needed()
|
|
verif_ca()
|
|
ca_generated = gen_ca(regen)
|
|
if merge:
|
|
merge_ca()
|
|
if ca_generated:
|
|
regen = True
|
|
certif_loader(regen=regen)
|
|
|
|
def verif_ca():
|
|
"""
|
|
vérifie que la ca est générée correctement (serial > 0xstart_index) et cn valide
|
|
"""
|
|
load_default_conf_if_needed()
|
|
# gestion des anciennes version de ca.crt
|
|
if os.path.isfile(ca_dest_file) and not os.path.isfile(ca_file):
|
|
# on reprend le premier certificat présent dans ca.crt dans ca_local.crt
|
|
ca_certs = open(ca_dest_file).read().strip()
|
|
tag_begin = '-----BEGIN CERTIFICATE-----'
|
|
try:
|
|
ca_data = tag_begin + ca_certs.split(tag_begin)[1]
|
|
local_ca = open(ca_file, 'w')
|
|
local_ca.write(ca_data)
|
|
local_ca.close()
|
|
except IndexError:
|
|
# impossible de reprendre la ca actuelle, elle sera regénérée
|
|
pass
|
|
serial = int(eval('0x%s'%start_index))
|
|
# vérification de la valeur actuelle du ca
|
|
# vérification du cn de la ca
|
|
if os.path.isfile(ca_file):
|
|
cmd = Popen(['/usr/bin/openssl', 'x509', '-in', ca_file, '-subject', '-noout'], stdout=PIPE)
|
|
if cmd.wait() != 0:
|
|
unlink(ca_file)
|
|
prep_dir()
|
|
if os.path.isfile(file_serial):
|
|
serial = open(file_serial).read().strip()
|
|
# conversion en hexa
|
|
serial = int(serial, 16)
|
|
if serial < min_serial:
|
|
if os.path.isfile(ca_file):
|
|
unlink(ca_file)
|
|
unlink(file_serial)
|
|
for f_index in glob.glob(os.path.join(ssl_dir, 'index*')):
|
|
unlink(f_index)
|
|
for f_cert in glob.glob(os.path.join(newcerts_dir, '*.pem')):
|
|
unlink(f_cert)
|
|
prep_dir()
|
|
|
|
def gen_ca(regen=False, del_passwd=True, extensions="SERVEUR"):
|
|
"""
|
|
Generation ca
|
|
"""
|
|
load_default_conf_if_needed()
|
|
generated = False
|
|
prep_dir()
|
|
if not os.path.isfile(ca_conf_file):
|
|
raise Exception(_(u"Certificate configuration template can not be found:\n\t{0}\n").format(ca_conf_file))
|
|
if regen or (not os.path.isfile(ca_keyfile)) or (not os.path.isfile(ca_file)):
|
|
print("* " + _(u"Generating CA certificate"))
|
|
remove_link(ca_file)
|
|
## On genère le certif de l'ac
|
|
ca_gen = '/usr/bin/openssl req -x509 -config %s -newkey rsa:%s -days %s -keyout "%s" -out "%s" -extensions %s >/dev/null 2>&1' % (ca_conf_file, ssl_default_key_bits, ssl_default_cert_time, tmp_keyfile, ca_file, extensions)
|
|
cmd = Popen(ca_gen, shell=True)
|
|
if cmd.wait() != 0:
|
|
raise Exception(_(u"Error while generating CA"))
|
|
if del_passwd:
|
|
sup_passwd(tmp_keyfile, ca_keyfile)
|
|
if os.path.isfile(tmp_keyfile):
|
|
unlink(tmp_keyfile)
|
|
generated = True
|
|
## application des droits
|
|
finalise_cert(ca_file, ca_keyfile, key_chmod='600')
|
|
build_link(ca_file)
|
|
## génération d'une crl
|
|
if not os.path.isfile(os.path.join(ssl_dir, 'eole.crl')):
|
|
print(_(u"Generating certificate revocation list (CRL)"))
|
|
crl_gen = '/usr/bin/openssl ca -gencrl -config %s -crldays %s -out %s/eole.crl >/dev/null 2>&1' % (ca_conf_file, ssl_default_cert_time, ssl_dir)
|
|
cmd = Popen(crl_gen, shell=True)
|
|
if cmd.wait() != 0:
|
|
raise Exception(_(u"Error while generating CRL ({0}/eole.crl)").format(ssl_dir))
|
|
return generated
|
|
|
|
def merge_ca():
|
|
"""
|
|
concatène toutes les ca utiles dans ca.crt
|
|
"""
|
|
load_default_conf_if_needed()
|
|
## concaténation des certificats education
|
|
ca_list = [ca_file, os.path.join(cert_dir, 'ACInfraEducation.pem')]
|
|
## concaténation de certificats supplémentaires si définis
|
|
for ca_perso in glob.glob(os.path.join(local_ca_dir,'*.*')):
|
|
if os.path.isfile(ca_perso):
|
|
ca_list.append(ca_perso)
|
|
concat_fic(ca_dest_file, ca_list, True, False)
|
|
|
|
def gen_certif(certfile, keyfile=None, key_user='', key_grp='', key_chmod='',
|
|
cert_user='', cert_grp='', cert_chmod='', regen=False, copy_key=False,
|
|
del_passwd=True, signe_req=True, container=None, client_cert=False,
|
|
cert_conf_file=None):
|
|
"""
|
|
Génération des requêtes de certificats et signature par la CA
|
|
"""
|
|
if not cert_conf_file:
|
|
if client_cert:
|
|
cert_conf_file = client_conf_file
|
|
else:
|
|
cert_conf_file = conf_file
|
|
load_default_conf_if_needed()
|
|
if not os.path.isfile(cert_conf_file):
|
|
raise Exception(_(u"Certificate configuration template can not be found:\n\t{0}\n").format(cert_conf_file))
|
|
|
|
basefile = os.path.splitext(certfile)[0]
|
|
if keyfile is None:
|
|
keyfile = "%s.key" % (basefile)
|
|
|
|
if container != None:
|
|
cpath = client.get_container(name=container)['path']
|
|
certfile = cpath + certfile
|
|
keyfile = cpath + keyfile
|
|
|
|
if regen or not os.path.isfile(certfile) or not os.path.isfile(keyfile):
|
|
|
|
remove_link(certfile)
|
|
if not isdir(dirname(certfile)):
|
|
raise Exception(_(u"Folder {0} does not exist.").format(dirname(certfile)))
|
|
if not isdir(dirname(keyfile)):
|
|
raise Exception(_(u"Folder {0} does not exist.").format(dirname(keyfile)))
|
|
|
|
# certificat absent ou regénération demandée
|
|
fic_p10 = os.path.join(req_dir, "%s.p10" % (os.path.basename(basefile)))
|
|
# génération de la requête de certificat x509 et d'un simili certificat auto-signé
|
|
if exists(keyfile):
|
|
gen_req = '/usr/bin/openssl req -new -key "%s" -days %s -config %s -out "%s" >/dev/null 2>&1' % (
|
|
keyfile, ssl_default_cert_time, cert_conf_file, fic_p10)
|
|
new_key = False
|
|
else:
|
|
gen_req = '/usr/bin/openssl req -new -newkey rsa:%s -days %s -config %s -keyout "%s" -out "%s" >/dev/null 2>&1' % (
|
|
ssl_default_key_bits, ssl_default_cert_time, cert_conf_file, tmp_keyfile, fic_p10)
|
|
new_key = True
|
|
cmd = Popen(gen_req, shell=True)
|
|
if cmd.wait() != 0:
|
|
raise Exception(_(u'! Error while generating certificate request {0} !').format(fic_p10))
|
|
if new_key:
|
|
if del_passwd:
|
|
sup_passwd(tmp_keyfile, keyfile)
|
|
else:
|
|
copy(tmp_keyfile, keyfile)
|
|
if os.path.isfile(tmp_keyfile):
|
|
unlink(tmp_keyfile)
|
|
if signe_req:
|
|
# on signe la requête
|
|
ca_signe = '/usr/bin/openssl ca -in "%s" -config %s -out "%s" -batch -notext >/dev/null 2>&1' % (fic_p10, cert_conf_file, certfile)
|
|
cmd = Popen(ca_signe, shell=True)
|
|
if cmd.wait() != 0:
|
|
raise Exception(_(u'! Error while signing certificate request {0} !') % fic_p10)
|
|
print(_(u"* Certificate {0} successfully generated").format(certfile))
|
|
if copy_key:
|
|
concat_fic(certfile, [keyfile], need_link=False)
|
|
finalise_cert(certfile, keyfile, key_user=key_user,
|
|
key_grp=key_grp, key_chmod=key_chmod,
|
|
cert_user=cert_user, cert_grp=cert_grp,
|
|
cert_chmod=cert_chmod)
|
|
build_link(certfile)
|
|
|
|
|
|
def remove_link(name, remove_broken_link=True):
|
|
load_default_conf_if_needed()
|
|
if not name.startswith(join(ssl_dir, 'certs')):
|
|
return
|
|
for cert_link in glob.glob(os.path.join(ssl_dir, 'certs/*')):
|
|
if islink(cert_link):
|
|
if remove_broken_link and not exists(cert_link):
|
|
#print 'ok lien cassé pour {} donc supprimé'.format(cert_link)
|
|
unlink(cert_link)
|
|
elif str(name) == realpath(cert_link):
|
|
#print 'ok suppression lien {} comme demandé ({})'.format(cert_link, name)
|
|
unlink(cert_link)
|
|
|
|
|
|
def build_link(name, concats=[]):
|
|
load_default_conf_if_needed()
|
|
if not name.startswith(join(ssl_dir, 'certs')):
|
|
return
|
|
def _check_contats_link(link):
|
|
# supprimer tous les liens vers les fichiers utilises pour la concatenation
|
|
if islink(link):
|
|
if realpath(link) in concats:
|
|
#print 'ok suppression du link {} ({} est dans {})'.format(link, realpath(link), concats)
|
|
unlink(link)
|
|
|
|
def _check_link(fp, suffix):
|
|
# calcul du bon suffix utilise dans le nom
|
|
# si le fichier existe avec le suffix courant, ajoute 1 au numero de suffix
|
|
new_name = join(dir_name, fp) + '.' + str(suffix)
|
|
if islink(new_name):
|
|
#print 'pas de suppression du link {} ({} n\'est pas dans {})'.format(new_name, realpath(new_name), concats)
|
|
return _check_link(fp, suffix + 1)
|
|
#else:
|
|
# print "ok ce n'est pas un link {}".format(new_name)
|
|
return new_name
|
|
|
|
def _build_link(ret):
|
|
# creer un lien a partir du hash du subject
|
|
if ret != '':
|
|
fp = ret.split('\n')[0]
|
|
if fp.isalnum():
|
|
if concats != []:
|
|
for link in glob.glob(join(dir_name, fp) + '.*'):
|
|
_check_contats_link(link)
|
|
|
|
new_name = _check_link(fp, 0)
|
|
#print 'ok creation du link {} vers {}'.format(new_name, name)
|
|
symlink(name, new_name)
|
|
return stat(new_name).st_mtime
|
|
return 0
|
|
|
|
dir_name = dirname(name)
|
|
subject_fp = ["/usr/bin/openssl", "x509", "-subject_hash", "-fingerprint", "-noout", "-in", name]
|
|
subject_fp_old = ["/usr/bin/openssl", "x509", "-subject_hash_old", "-fingerprint", "-noout", "-in", name]
|
|
new_timestamp = _build_link(system_out(subject_fp)[1])
|
|
new_timestamp = max(_build_link(system_out(subject_fp_old)[1]), new_timestamp)
|
|
if isfile(SSL_LAST_FILE):
|
|
try:
|
|
fh = open(SSL_LAST_FILE, 'r')
|
|
timestamp = float(fh.read().strip())
|
|
except ValueError:
|
|
timestamp = 0
|
|
if new_timestamp > timestamp:
|
|
fh = open(SSL_LAST_FILE, 'w')
|
|
fh.write(str(new_timestamp))
|
|
fh.close()
|
|
|
|
|
|
def rehash_if_needed():
|
|
load_default_conf_if_needed()
|
|
need_rehash = False
|
|
if isfile(SSL_LAST_FILE):
|
|
try:
|
|
fh = open(SSL_LAST_FILE, 'r')
|
|
timestamp = int(float(fh.read().strip()))
|
|
for cert_link in glob.glob(os.path.join(ssl_dir, 'certs/*')):
|
|
try:
|
|
if timestamp < int(stat(cert_link).st_mtime):
|
|
need_rehash = True
|
|
break
|
|
except:
|
|
pass
|
|
except ValueError:
|
|
import traceback
|
|
traceback.print_exc()
|
|
need_rehash = True
|
|
else:
|
|
need_rehash = True
|
|
|
|
if need_rehash:
|
|
system_code(['/usr/bin/c_rehash'])
|
|
new_timestamp = 0
|
|
for cert_link in glob.glob(os.path.join(ssl_dir, 'certs/*')):
|
|
if isfile(cert_link):
|
|
timestamp = stat(cert_link).st_mtime
|
|
if timestamp > new_timestamp:
|
|
new_timestamp = timestamp
|
|
fh = open(SSL_LAST_FILE, 'w')
|
|
fh.write(str(new_timestamp))
|
|
fh.close()
|
|
|
|
|
|
# gen_certif utils reader
|
|
|
|
def certif_loader(regen=None):
|
|
"""charge les fichiers permettant de générer les certificats
|
|
"""
|
|
load_default_conf_if_needed()
|
|
# XXX FIXME : changer le path de data vers les paquets container,
|
|
# XXX FIXME et déplacer les .gen_cert
|
|
files = glob.glob(join('/usr/share/eole/certs', '*_*.gen_cert'))
|
|
files.sort()
|
|
for fname in files:
|
|
# puts name in global namespace because we need it in execfile's
|
|
# namespace in rules_loader
|
|
name = splitext(basename(fname))[0].split('_')[1]
|
|
# exec gen_certs
|
|
execfile(fname, globals(),locals())
|
|
|
|
def get_subject(cert=None, certfile=None):
|
|
"""
|
|
récupère le subject d'un certificat.
|
|
spécifier obligatoirement un des deux paramètres :
|
|
- cert : contenu du certificat
|
|
- certfile : nom du fichier du certificat
|
|
"""
|
|
load_default_conf_if_needed()
|
|
global regexp_get_subject
|
|
if None not in (cert, certfile):
|
|
raise Exception(_(u'cert or certfile must be None'))
|
|
if cert == certfile:
|
|
raise Exception(_(u'cert or certfile must be set'))
|
|
if certfile != None:
|
|
cmd = ['openssl', 'x509', '-in', certfile, '-subject', '-noout']
|
|
stdin = None
|
|
else:
|
|
cmd = ['openssl', 'x509', '-subject', '-noout']
|
|
stdin = cert
|
|
ret = system_out(cmd=cmd, stdin=stdin)
|
|
if ret[0] != 0:
|
|
raise Exception(_(u'error in {0}: {1}').format(' '.join(cmd), str(ret[2])))
|
|
ret = ret[1].rstrip()
|
|
if not ret.startswith("subject= "):
|
|
raise Exception(_(u'Invalid certificate subject: {0} ').format(ret))
|
|
if regexp_get_subject is None:
|
|
regexp_get_subject = re.compile('^subject= (.*)/CN=(.*)')
|
|
return regexp_get_subject.findall(ret)[0]
|
|
|
|
def get_issuer_subject(cert=None, certfile=None):
|
|
"""
|
|
récupère le subject de la CA d'un certificat.
|
|
spécifier obligatoirement un des deux paramètres :
|
|
- cert : contenu du certificat
|
|
- certfile : nom du fichier du certificat
|
|
"""
|
|
load_default_conf_if_needed()
|
|
if None not in (cert, certfile):
|
|
raise Exception(_(u'cert or certfile must be None'))
|
|
if cert == certfile:
|
|
raise Exception(_(u'cert or certfile must be set'))
|
|
if certfile != None:
|
|
cmd = ['openssl', 'x509', '-in', certfile, '-issuer', '-noout']
|
|
stdin = None
|
|
else:
|
|
cmd = ['openssl', 'x509', '-issuer', '-noout']
|
|
stdin = cert
|
|
ret = system_out(cmd=cmd, stdin=stdin)
|
|
if ret[0] != 0:
|
|
raise Exception(_(u'error in {0}: {1}').format(' '.join(cmd), str(ret[2])))
|
|
ret = ret[1].rstrip()
|
|
if not ret.startswith("issuer= "):
|
|
raise Exception(_(u'Invalid certificate issuer: {0} ').format(ret))
|
|
regexp = '^issuer= (.*)/CN=(.*)'
|
|
return re.findall(regexp, ret)[0]
|
|
|
|
def load_conf(ssl_dico):
|
|
global ssl_dir, cert_dir, key_dir, tmp_keyfile, file_serial, req_dir
|
|
global local_ca_dir, newcerts_dir, ca_conf_file, conf_file, client_conf_file
|
|
global ca_file, ca_dest_file, ca_keyfile, start_index, min_serial
|
|
global ssl_default_key_bits, ssl_default_cert_time
|
|
global certs_catalog
|
|
|
|
ssl_dir = ssl_dico.get('ssl_dir', ssl_dir)
|
|
cert_dir = ssl_dico.get('cert_dir', os.path.join(ssl_dir, "certs"))
|
|
key_dir = ssl_dico.get('key_dir', os.path.join(ssl_dir, "private"))
|
|
tmp_keyfile = ssl_dico.get('tmp_keyfile', os.path.join(key_dir, "tmpkey.key"))
|
|
file_serial = ssl_dico.get('file_serial', os.path.join(ssl_dir, "serial"))
|
|
req_dir = ssl_dico.get('req_dir', os.path.join(ssl_dir, "req"))
|
|
local_ca_dir = ssl_dico.get('local_ca_dir', os.path.join(ssl_dir, "local_ca"))
|
|
newcerts_dir = ssl_dico.get('newcerts_dir', os.path.join(ssl_dir, "newcerts"))
|
|
ca_conf_file = ssl_dico.get('ca_conf_file', ca_conf_file)
|
|
conf_file = ssl_dico.get('conf_file', conf_file)
|
|
client_conf_file = ssl_dico.get('client_conf_file', conf_file)
|
|
# chemin de la CA
|
|
ca_file = ssl_dico.get('ca_file', os.path.join(cert_dir, "ca_local.crt"))
|
|
ca_dest_file = ssl_dico.get('ca_dest_file', os.path.join(cert_dir, "ca.crt"))
|
|
ca_keyfile = ssl_dico.get('ca_keyfile', os.path.join(key_dir, "ca.key"))
|
|
# index
|
|
start_index = ssl_dico.get('start_index', hex(int(time.time()))[2:])
|
|
min_serial = int(eval('0x30'))
|
|
ssl_default_key_bits = ssl_dico.get('ssl_default_key_bits', client.get_creole('ssl_default_key_bits', 2048))
|
|
ssl_default_cert_time = ssl_dico.get('ssl_default_cert_time', client.get_creole('ssl_default_cert_time', 1096))
|
|
|
|
def load_default_conf_if_needed():
|
|
"""creoled n'est pas forcement démarré à ce moment là
|
|
ne charger la configuration par défaut qu'à l'utilisation de la lib
|
|
et non a l'importantion
|
|
#8448
|
|
"""
|
|
global ssl_dir
|
|
if ssl_dir == None:
|
|
load_conf({'ssl_dir': '/etc/ssl',
|
|
'ca_conf_file': '/etc/eole/ssl/ca-eole.conf',
|
|
'conf_file': '/etc/eole/ssl/certif-eole.conf',
|
|
'client_conf_file': '/etc/eole/ssl/client-eole.conf'})
|
|
|
|
ssl_dir=None
|
|
ca_conf_file=None
|
|
client_conf_file=None
|
|
conf_file=None
|
|
certs_catalog = None
|
|
ca_issuer = None
|