You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-3-core/pym/core/server/bootstrap.py

502 lines
17 KiB

9 years ago
# -*- coding: utf-8 -*-
12 years ago
# Copyright 2012-2016 Mir Calculate. http://www.calculate-linux.org
12 years ago
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
3 years ago
from . import cert_cmd
from . import post_request
9 years ago
import datetime
import subprocess
import shutil
12 years ago
from calculate.core.client.cert_func import new_key_req
from calculate.core.client.function import get_ip_mac_type
from calculate.core.datavars import DataVarsCore
from calculate.lib.utils.files import (makeDirectory, pathJoin, readFile,
writeFile, readFileEx)
from calculate.lib.utils.mount import isMount
from calculate.core.server.admin import Admins
9 years ago
import os
import hashlib
import pwd
import socket
import sys
import re
9 years ago
_ = lambda x: x
from calculate.lib.cl_lang import setLocalTranslate
12 years ago
9 years ago
setLocalTranslate('cl_core3', sys.modules[__name__])
def parse_cert_date(date):
year = int(date[:4])
month = int(date[4:6])
day = int(date[6:8])
hour = int(date[8:10])
minute = int(date[10:12])
sec = int(date[12:14])
return datetime.datetime(year, month, day, hour, minute, sec)
9 years ago
def check(cert, key):
error_flag = 0
if not os.path.isfile(cert):
error_flag = 1
3 years ago
print(_('Certificate %s not found') % cert)
print(key, cert)
if not os.path.isfile(key):
error_flag = 1
3 years ago
print(_('Private key %s not found') % key)
if os.path.isfile(cert) and os.path.isfile(key):
import OpenSSL
# check correspondence certificate and private key
cmd_cert = 'openssl x509 -noout -modulus -in ' + cert
cmd_key = 'openssl rsa -noout -modulus -in ' + key
9 years ago
p_cert = subprocess.Popen(cmd_cert.split(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p_key = subprocess.Popen(cmd_key.split(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if not p_cert.stdout.read().strip() == p_key.stdout.read().strip():
3 years ago
print(_('The certificate does not match the private key'))
error_flag = 1
# check certificate date
cert_data = readFile(cert)
9 years ago
certobj = OpenSSL.crypto.load_certificate(
OpenSSL.SSL.FILETYPE_PEM, cert_data)
certobj.get_notBefore()
9 years ago
try:
not_after = parse_cert_date(certobj.get_notAfter())
not_before = parse_cert_date(certobj.get_notBefore())
date = datetime.datetime.now()
if not_before > date:
3 years ago
print(_('Certificate creation date later than current date'))
9 years ago
error_flag = 1
elif not_after < date:
3 years ago
print(_('Certificate expired'))
9 years ago
error_flag = 1
except ValueError:
3 years ago
print(_('Failed to get certificate work date'))
error_flag = 1
9 years ago
sys.exit(error_flag)
9 years ago
def init(cert, key, cert_path, data_path, certbase, args, port):
if args.remove_certificates:
key_force(cert_path, data_path)
new_serv_cert = False
if not check_serv_cert(cert_path):
3 years ago
print(_('Generating the server certificate'))
9 years ago
for step in range(2):
12 years ago
args = change_args(args, step)
create_server_cert(cert, key, cert_path, args, port)
new_serv_cert = True
else:
3 years ago
print(_('Server certificate now exists.'))
3 years ago
os.chmod(data_path, 0o700)
def force_user_cert(server_cert, cert_path, data_path, cert_base, user_name,
dv=None):
def is_crypthome_notmount(dv, username):
dv.Set('ur_login', user_name, force=True)
homedir = dv.Get('ur_home_path')
if (dv.GetBool('ur_home_crypt_set') and
'.Private' not in isMount(homedir)):
return True
return False
if not check_client_cert(user_name, server_cert=server_cert):
3 years ago
print(_('Generating the client certificate'))
else:
3 years ago
print(_('Regenerating the client certificate'))
group = "all"
if dv:
admins = Admins(dv)
if user_name not in admins:
admins[user_name] = group
admins.save()
group = admins[user_name]
if is_crypthome_notmount(dv, user_name):
3 years ago
print(_("User profile is encrypted. Please perform user login for "
"complete of certificate generation"))
return
create_client_cert(server_cert, cert_path, data_path, cert_base,
user_name, group)
def check_serv_cert(cert_path):
if os.path.isfile(os.path.join(cert_path, 'server.crt')) and \
9 years ago
os.path.isfile(os.path.join(cert_path, 'server.key')):
return True
return False
9 years ago
def check_client_cert(user_name, server_cert=None):
client_cert_path = check_user_path(user_name)
if server_cert:
server_host_name = get_certificate_dn(server_cert)
else:
server_host_name = socket.getfqdn()
9 years ago
crt_fn = os.path.join(client_cert_path, server_host_name + '.crt')
key_fn = os.path.join(client_cert_path, server_host_name + '.key')
if os.path.isfile(crt_fn) and os.path.isfile(key_fn):
return True
return False
12 years ago
9 years ago
def change_args(args, step=None):
12 years ago
if step == 0:
args.host = False
args.gen_root_cert = True
args.root_host = False
args.use_root_cert = False
elif step == 1:
args.gen_root_cert = False
args.use_root_cert = True
return args
12 years ago
9 years ago
12 years ago
def create_server_cert(cert, key, cert_path, args, port):
9 years ago
cert_cmd.check_server_certificate(cert, key, cert_path, args, port,
auto=True)
12 years ago
def create_client_cert(server_cert, cert_path, data_path, certbase, user_name,
group="all"):
client_cert_path = check_user_path(user_name)
if not client_cert_path:
3 years ago
print(_('no path to the client certificate'))
return 1
9 years ago
req_id = create_request(server_cert, cert_path, data_path, certbase,
client_cert_path, user_name)
sign_certificate(req_id, cert_path, data_path, group)
get_certificate(cert_path, data_path, certbase, client_cert_path, user_name,
server_cert=server_cert)
9 years ago
12 years ago
def check_user_path(user_name):
try:
pwdObj = pwd.getpwnam(user_name)
9 years ago
except KeyError as e:
3 years ago
print(e)
return None
home_dir = pwdObj.pw_dir
if not os.path.isdir(home_dir):
if not makeDirectory(home_dir):
return None
os.chown(home_dir, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(home_dir, 0o700)
calc_dir = os.path.join(home_dir, '.calculate')
cert_dir = os.path.join(calc_dir, 'client_cert')
for directory in [calc_dir, cert_dir]:
if not os.path.isdir(directory):
if not makeDirectory(directory):
return None
os.chown(directory, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(directory, 0o755)
for path in os.walk(cert_dir):
os.chown(path[0], pwdObj.pw_uid, pwdObj.pw_gid)
for _file in path[2]:
9 years ago
fn = pathJoin(path[0], _file)
if os.path.isfile(fn):
os.chown(fn, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(fn, 0o644)
return cert_dir
12 years ago
9 years ago
def create_request(server_cert, cert_path, data_path, certbase,
client_cert_path, user_name):
server_host_name = get_certificate_dn(server_cert)
12 years ago
key = os.path.join(client_cert_path, server_host_name + '.key')
12 years ago
client_req_file = new_key_req(key, client_cert_path, server_host_name,
9 years ago
auto=True)
12 years ago
try:
pwdObj = pwd.getpwnam(user_name)
9 years ago
except KeyError as e:
3 years ago
print(e)
return None
9 years ago
for files in [client_req_file, key + '_pub']:
if os.path.exists(files):
9 years ago
os.chown(files, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(files, 0o644)
if os.path.exists(key):
9 years ago
os.chown(key, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(key, 0o600)
12 years ago
ip, mac, client_type = get_ip_mac_type()
data = readFile(client_req_file)
12 years ago
9 years ago
req_id = post_request.serv_post_client_request(
data, data_path, ip, mac, client_type, certbase, cert_path)
12 years ago
fc = open(os.path.join(client_cert_path, 'req_id'), 'w')
fc.write(req_id)
12 years ago
fc.close()
return req_id
12 years ago
9 years ago
def sign_certificate(req_id, cert_path, data_path, group="all"):
cert_cmd.sing_req_by_server(req_id, cert_path, data_path, auto=True,
group_name=group)
12 years ago
9 years ago
def get_certificate_dn(cert_file):
cert_data = readFile(cert_file)
if cert_data:
import OpenSSL
certobj = OpenSSL.crypto.load_certificate(
OpenSSL.SSL.FILETYPE_PEM, cert_data)
cert_info = dict(certobj.get_subject().get_components())
return cert_info["CN"]
return "localhost"
def clear_localuser_certificates(certbase):
"""
Удалить все пользовательские сертификаты, создаваемые для локальных
пользователей
"""
certdata = readFileEx(certbase, grab=True)
certdn = os.path.dirname(certbase)
# оставляем только сертификаты, которые не содержат отметки
# для какого локального пользователя они созданы
writedata = "\n".join(x[0] for x in re.findall("^((\S+\s+){6}\S+)\s*$",
certdata, flags=re.M))
with writeFile(certbase) as f:
f.write("%s\n"%writedata)
# удаляем физически сертификаты, созданные для локальных пользователей
for localcert in re.finditer("^(\S+)\s+(\S+\s+){6}\S+\s*$",
certdata, flags=re.M):
cert_fn = "%s/%s.crt"%(certdn, localcert.group(1))
try:
os.unlink(cert_fn)
except OSError:
3 years ago
print(_("Failed to remove local client certificate") % cert_fn)
9 years ago
def get_certificate(cert_path, data_path, certbase, client_cert_path,
user_name, server_cert=None):
req_id_file = os.path.join(client_cert_path, 'req_id')
if not os.path.exists(req_id_file):
3 years ago
print(_("request not sent or file %s deleted") % req_id_file)
12 years ago
return 1
fc = open(req_id_file, 'r')
12 years ago
req_id = fc.read()
fc.close()
if server_cert:
server_host_name = get_certificate_dn(server_cert)
else:
server_host_name = socket.getfqdn()
req_file = os.path.join(client_cert_path, server_host_name + '.csr')
if not os.path.exists(req_file):
3 years ago
print(_('Request %s not found') % req_file)
12 years ago
return 1
request = readFile(req_file)
12 years ago
md5 = hashlib.md5()
md5.update(request.encode("UTF-8"))
12 years ago
md5sum = md5.hexdigest()
12 years ago
9 years ago
result = post_request.serv_get_client_cert(
req_id, md5sum, data_path, certbase, cert_path,
localuser=user_name)
12 years ago
cert = result[0]
9 years ago
if len(result) > 1:
ca_root = result[1]
9 years ago
else:
return None
12 years ago
if cert == '1':
3 years ago
print(_('The signature request was rejected!'))
12 years ago
return 1
elif cert == '2':
3 years ago
print(_("The signature request has not been examined yet."))
print(_("Your request ID = %s") % req_id)
12 years ago
return 1
elif cert == '3':
3 years ago
print(_("The signature request does not match earlier data."))
12 years ago
return 1
elif cert == '4':
3 years ago
print(_("The request was sent from another IP."))
12 years ago
return 1
cert_file = os.path.join(client_cert_path, server_host_name + '.crt')
fc = open(cert_file, 'w')
12 years ago
fc.write(cert)
fc.close()
try:
pwdObj = pwd.getpwnam(user_name)
3 years ago
except KeyError as e:
print(e)
return None
os.chown(cert_file, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(cert_file, 0o600)
os.unlink(req_id_file)
3 years ago
print(_('Certificate saved. Your certificate ID: %s') % req_id)
12 years ago
12 years ago
if ca_root:
clVars = DataVarsCore()
clVars.importCore()
12 years ago
clVars.flIniFile()
system_ca_db = clVars.Get('cl_glob_root_cert')
if os.path.exists(system_ca_db):
if ca_root in readFile(system_ca_db):
12 years ago
return 0
12 years ago
ca_dir = os.path.join(client_cert_path, 'ca')
if not os.path.isdir(ca_dir):
os.makedirs(ca_dir)
os.chown(ca_dir, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(ca_dir, 0o755)
root_cert_md5 = os.path.join(ca_dir, "cert_list")
12 years ago
md5 = hashlib.md5()
md5.update(ca_root.encode("UTF-8"))
12 years ago
md5sum = md5.hexdigest()
12 years ago
12 years ago
if not os.path.exists(root_cert_md5):
9 years ago
fc = open(root_cert_md5, "w")
12 years ago
fc.close()
12 years ago
12 years ago
filename = None
with open(root_cert_md5) as fd:
t = fd.read()
# for each line
for line in t.splitlines():
# Split string into a words list
9 years ago
words = line.split(' ', 1)
12 years ago
if words[0] == md5sum:
filename = words[1]
if not filename:
import OpenSSL
9 years ago
certobj = OpenSSL.crypto.load_certificate(
OpenSSL.SSL.FILETYPE_PEM, ca_root)
issuer = certobj.get_issuer().get_components()
for item in issuer:
12 years ago
if item[0] == 'CN':
filename = item[1]
12 years ago
9 years ago
fc = open(root_cert_md5, "a")
fc.write('%s %s\n' % (md5sum, filename))
12 years ago
fc.close()
os.chown(root_cert_md5, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(root_cert_md5, 0o644)
12 years ago
12 years ago
if not filename:
3 years ago
print(_('Field "CN" not found in the certificate!'))
12 years ago
return 1
12 years ago
ca_cert = os.path.join(ca_dir, filename)
fd = open(ca_cert, 'w')
12 years ago
fd.write(ca_root)
fd.close()
os.chown(ca_cert, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(ca_cert, 0o644)
12 years ago
user_root_cert = os.path.join(ca_dir, 'ca_root.crt')
12 years ago
fa = open(user_root_cert, 'a')
fa.write(ca_root)
fa.close()
os.chown(user_root_cert, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(user_root_cert, 0o644)
9 years ago
# print _("Certificate added")
# else:
# print _("file with the CA certificate now exists")
trust_dir = os.path.join(client_cert_path, 'trusted')
if not os.path.isdir(trust_dir):
os.makedirs(trust_dir)
os.chown(trust_dir, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(trust_dir, 0o755)
ca_certs = os.path.join(trust_dir, "cert.list")
if not os.path.exists(ca_certs):
9 years ago
fc = open(ca_certs, "w")
fc.close()
os.chown(ca_certs, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(ca_certs, 0o644)
host = 'localhost'
filename = host
cert_file_trust = os.path.join(trust_dir, filename)
9 years ago
fc = open(cert_file_trust, "w")
fc.write(ca_root)
fc.close()
os.chown(cert_file_trust, pwdObj.pw_uid, pwdObj.pw_gid)
3 years ago
os.chmod(cert_file_trust, 0o644)
with open(ca_certs) as fd:
t = fd.read()
# for each line
for line in t.splitlines():
# Split string into a words list
words = line.split()
if len(words) > 1:
# if first word...
if words[0] == host:
return 0
# Open file with compliance server certificates and server hostname
9 years ago
fcl = open(ca_certs, "a")
fcl.write(host + ' ' + filename + '\n')
fcl.close()
return 0
9 years ago
def key_force(cert_path, data_path):
while True:
try:
resp = input(_('Do you really want to remove all '
9 years ago
'certificates, requests and config files from '
'the server?') + ' (yes/no): ')
except KeyboardInterrupt:
resp = 'no'
if resp.lower() in ['n', 'no']:
return 0
elif resp.lower() in ['y', 'yes']:
break
if os.path.isdir(cert_path):
shutil.rmtree(cert_path)
9 years ago
remove_dirs = ['conf', 'server_certs', 'client_certs', 'pids', 'sids']
for rm_dir in remove_dirs:
remove_dir = os.path.join(data_path, rm_dir)
if os.path.isdir(remove_dir):
shutil.rmtree(remove_dir)
remove_files = ['sid.db', 'sid_pid']
for rm_file in remove_files:
remove_file = os.path.join(data_path, rm_file)
if os.path.isfile(remove_file):
os.unlink(remove_file)