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

453 lines
15 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.
import cert_cmd
12 years ago
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
9 years ago
import os
import hashlib
import pwd
import socket
import sys
_ = 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
9 years ago
print _('Certificate %s not found') % cert
print key, cert
if not os.path.isfile(key):
error_flag = 1
9 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():
12 years ago
print _('The certificate does not match the private key')
error_flag = 1
# check certificate date
cert_data = open(cert, 'r').read()
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:
print _('Certificate creation date later than current date')
error_flag = 1
elif not_after < date:
print _('Certificate expired')
error_flag = 1
except ValueError:
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, user_name):
if args.remove_certificates:
key_force(cert_path, data_path)
new_serv_cert = False
if not check_serv_cert(cert_path):
12 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:
12 years ago
print _('Server certificate now exists.')
if new_serv_cert or not check_client_cert(user_name):
12 years ago
print _('Generating the client certificate')
create_client_cert(cert, cert_path, data_path, certbase, user_name)
else:
12 years ago
print _('Client certificate now exists.')
9 years ago
def force_user_cert(server_cert, cert_path, data_path, cert_base, user_name):
if not check_client_cert(user_name, server_cert=server_cert):
print _('Generating the client certificate')
else:
print _('Regenerating the client certificate')
create_client_cert(server_cert, cert_path, data_path, cert_base, user_name)
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):
client_cert_path = check_user_path(user_name)
if not client_cert_path:
12 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)
12 years ago
sign_certificate(req_id, cert_path, data_path)
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:
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)
os.chmod(home_dir, 0700)
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)
os.chmod(directory, 0755)
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)
os.chmod(fn, 0644)
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:
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)
os.chmod(files, 0644)
if os.path.exists(key):
9 years ago
os.chown(key, pwdObj.pw_uid, pwdObj.pw_gid)
os.chmod(key, 0600)
12 years ago
ip, mac, client_type = get_ip_mac_type()
data = open(client_req_file).read()
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
12 years ago
def sign_certificate(req_id, cert_path, data_path):
9 years ago
cert_cmd.sing_req_by_server(req_id, cert_path, data_path, auto=True)
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"
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):
9 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()
12 years ago
req_file = os.path.join(client_cert_path, server_host_name + '.csr')
if not os.path.exists(req_file):
9 years ago
print _('Request %s not found') % req_file
12 years ago
return 1
request = open(req_file).read()
12 years ago
md5 = hashlib.md5()
md5.update(request)
md5sum = md5.hexdigest()
12 years ago
9 years ago
result = post_request.serv_get_client_cert(
req_id, md5sum, data_path, certbase, cert_path)
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':
12 years ago
print _('The signature request was rejected!')
12 years ago
return 1
elif cert == '2':
12 years ago
print _("The signature request has not been examined yet.")
9 years ago
print _("Your request ID = %s") % req_id
12 years ago
return 1
elif cert == '3':
12 years ago
print _("The signature request does not match earlier data.")
12 years ago
return 1
elif cert == '4':
12 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)
except KeyError, e:
print e
return None
os.chown(cert_file, pwdObj.pw_uid, pwdObj.pw_gid)
os.chmod(cert_file, 0600)
os.unlink(req_id_file)
9 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 open(system_ca_db, 'r').read():
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)
os.chmod(ca_dir, 0755)
root_cert_md5 = os.path.join(ca_dir, "cert_list")
12 years ago
md5 = hashlib.md5()
md5.update(ca_root)
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)
os.chmod(root_cert_md5, 0644)
12 years ago
12 years ago
if not filename:
12 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)
os.chmod(ca_cert, 0644)
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)
os.chmod(user_root_cert, 0644)
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)
os.chmod(trust_dir, 0755)
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)
os.chmod(ca_certs, 0644)
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)
os.chmod(cert_file_trust, 0644)
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:
12 years ago
resp = raw_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)