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.
323 lines
10 KiB
323 lines
10 KiB
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2012-2016 Mir Calculate. http://www.calculate-linux.org
|
|
#
|
|
# 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 os
|
|
import sys
|
|
from sid_func import client_sid
|
|
from function import get_sid, get_ip_mac_type
|
|
from create_cert import (generateRSAKey, makePKey,
|
|
makeRequest, passphrase_callback)
|
|
import hashlib
|
|
from client_class import HTTPSClientCertTransport
|
|
from cert_verify import VerifyError
|
|
from calculate.core.datavars import DataVarsCore
|
|
from calculate.lib.utils.files import readFile
|
|
|
|
VERSION = 0.11
|
|
|
|
_ = lambda x: x
|
|
from calculate.lib.cl_lang import setLocalTranslate
|
|
|
|
setLocalTranslate('cl_core3', sys.modules[__name__])
|
|
|
|
|
|
def client_post_cert(client):
|
|
""" send a certificate server for check """
|
|
sid = get_sid(client.SID_FILE)
|
|
results = client.service.post_cert()
|
|
|
|
if results[0][0] == -4:
|
|
print _("Certificate not found in the server database!")
|
|
sys.exit(1)
|
|
client_sid(sid, client, cert_id=results[0][0])
|
|
if results[0][0] == -3:
|
|
print _("Certificate not sent!")
|
|
else:
|
|
print _(" Your certifitate ID = %d") % (results[0][0])
|
|
try:
|
|
if results[0][1] == -2:
|
|
print _("Certificate expired")
|
|
elif results[0][1] > 0:
|
|
print _("The certificate expires after %d days") % (
|
|
results[0][1])
|
|
except (IndexError, AttributeError):
|
|
pass
|
|
|
|
|
|
# Creation of secret key of the client
|
|
def new_key_req(key, cert_path, server_host_name, auto=False):
|
|
rsa = generateRSAKey()
|
|
rsa.save_key(key + '_pub', cipher=None, callback=passphrase_callback)
|
|
|
|
pkey = makePKey(rsa)
|
|
pkey.save_key(key, cipher=None, callback=passphrase_callback)
|
|
|
|
req = makeRequest(rsa, pkey, server_host_name, auto)
|
|
crtreq = req.as_pem()
|
|
|
|
req_file = os.path.join(cert_path, '%s.csr' % server_host_name)
|
|
crtfile = open(req_file, 'w')
|
|
crtfile.write(crtreq)
|
|
crtfile.close()
|
|
return req_file
|
|
|
|
|
|
def delete_old_cert(client):
|
|
os.unlink(client.CERT_FILE)
|
|
os.unlink(client.REQ_FILE)
|
|
os.unlink(client.PKEY_FILE)
|
|
os.unlink(client.PubKEY_FILE)
|
|
|
|
|
|
def client_post_request(cert_path, by_host):
|
|
if os.path.exists(cert_path + 'req_id'):
|
|
print _("You already sent a certificate signature request.")
|
|
print _("Request ID = %s") % readFile(cert_path + 'req_id')
|
|
ans = raw_input(_("Send a new request? y/[n]: "))
|
|
if not ans.lower() in ['y', 'yes']:
|
|
return 0
|
|
|
|
port = raw_input(_("Enter the port number: "))
|
|
try:
|
|
port = int(port)
|
|
except ValueError:
|
|
print _('The port number must be int')
|
|
return 1
|
|
url = "https://%s:%d/?wsdl" % (by_host, port)
|
|
print url + '\n' + _("connecting...")
|
|
# from sudsds.client import Client
|
|
from suds.client import Client
|
|
# try:
|
|
client = Client(url, transport=HTTPSClientCertTransport(None, None,
|
|
cert_path))
|
|
# except (KeyboardInterrupt, urllib2.URLError), e:
|
|
# print '\n'+_("Closed. Connection error.")
|
|
# print _("Error code: %s") %e
|
|
# return 0
|
|
|
|
server_host_name = client.service.get_server_host_name()
|
|
|
|
key = cert_path + server_host_name + '.key'
|
|
csr_file = cert_path + server_host_name + '.csr'
|
|
if os.path.exists(key) and os.path.exists(csr_file):
|
|
print _("the private key and request now exist")
|
|
ask = raw_input(_("Create a new private key and request? y/[n]: "))
|
|
if ask.lower() in ['y', 'yes']:
|
|
new_key_req(key, cert_path, server_host_name)
|
|
else:
|
|
new_key_req(key, cert_path, server_host_name)
|
|
|
|
ip, mac, client_type = get_ip_mac_type()
|
|
data = readFile(csr_file)
|
|
res = client.service.post_client_request(request=data, ip=ip,
|
|
mac=mac, client_type=client_type)
|
|
if int(res) < 0:
|
|
print _("This server is not enabled to sign certificates!")
|
|
return 1
|
|
fc = open(cert_path + 'req_id', 'w')
|
|
fc.write(res)
|
|
fc.close()
|
|
print _("Your request ID = %s") % res
|
|
return 0
|
|
|
|
|
|
def client_get_cert(cert_path, args):
|
|
if not os.path.exists(cert_path + 'req_id'):
|
|
print _("request not sent or file %s deleted") % (cert_path + 'req_id')
|
|
return 1
|
|
fc = open(cert_path + 'req_id', 'r')
|
|
req_id = fc.read()
|
|
fc.close()
|
|
|
|
print '\n' + _("the URL looks like"), "https://%s:[port]/?wsdl" \
|
|
% args.from_host
|
|
port = raw_input(_("Enter the port number: "))
|
|
try:
|
|
port = int(port)
|
|
except ValueError:
|
|
print _('The port number must be int')
|
|
return 1
|
|
url = "https://%s:%d/?wsdl" % (args.from_host, port)
|
|
print url + '\n' + _("connecting...")
|
|
|
|
# from sudsds.client import Client
|
|
from suds.client import Client
|
|
|
|
try:
|
|
client = Client(url, transport=HTTPSClientCertTransport(None, None,
|
|
cert_path))
|
|
except KeyboardInterrupt:
|
|
print '\n' + _("Closed. Connection error.")
|
|
return 1
|
|
|
|
server_host_name = client.service.get_server_host_name()
|
|
|
|
if not os.path.exists(cert_path + server_host_name + '.csr'):
|
|
print _('Request %s not found') % (
|
|
cert_path + server_host_name + '.csr')
|
|
return 1
|
|
request = readFile(cert_path + server_host_name + '.csr')
|
|
md5 = hashlib.md5()
|
|
md5.update(request)
|
|
md5sum = md5.hexdigest()
|
|
|
|
result = client.service.get_client_cert(req_id, md5sum)
|
|
cert = result[0][0]
|
|
ca_root = result[0][1]
|
|
if cert == '1':
|
|
print _('The signature request was rejected!')
|
|
return 1
|
|
elif cert == '2':
|
|
print _("The signature request has not been examined yet.")
|
|
print _("Your request ID = %s") % req_id
|
|
return 1
|
|
elif cert == '3':
|
|
print _("The signature request does not match earlier data.")
|
|
return 1
|
|
elif cert == '4':
|
|
print _("The request was sent from another IP.")
|
|
return 1
|
|
fc = open(cert_path + server_host_name + '.crt', 'w')
|
|
fc.write(cert)
|
|
fc.close()
|
|
os.unlink(cert_path + 'req_id')
|
|
print 'OK. Certificate saved. Your certificate ID = %s' % req_id
|
|
|
|
if ca_root:
|
|
cl_vars = DataVarsCore()
|
|
cl_vars.importCore()
|
|
cl_vars.flIniFile()
|
|
system_ca_db = cl_vars.Get('cl_glob_root_cert')
|
|
if os.path.exists(system_ca_db):
|
|
if ca_root in readFile(system_ca_db):
|
|
return 0
|
|
|
|
cl_client_cert_dir = cl_vars.Get('cl_client_cert_dir')
|
|
home_path = cl_vars.Get('ur_home_path')
|
|
|
|
cl_client_cert_dir = cl_client_cert_dir.replace("~", home_path)
|
|
root_cert_md5 = cl_client_cert_dir + "/ca/cert_list"
|
|
|
|
md5 = hashlib.md5()
|
|
md5.update(ca_root)
|
|
md5sum = md5.hexdigest()
|
|
|
|
if not os.path.exists(root_cert_md5):
|
|
fc = open(root_cert_md5, "w")
|
|
fc.close()
|
|
|
|
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
|
|
words = line.split(' ', 1)
|
|
if words[0] == md5sum:
|
|
filename = words[1]
|
|
import OpenSSL
|
|
|
|
if not filename:
|
|
certobj = OpenSSL.crypto.load_certificate(
|
|
OpenSSL.SSL.FILETYPE_PEM, ca_root)
|
|
issuer = certobj.get_issuer().get_components()
|
|
for item in issuer:
|
|
if item[0] == 'CN':
|
|
filename = item[1]
|
|
|
|
fc = open(root_cert_md5, "a")
|
|
fc.write('%s %s\n' % (md5sum, filename))
|
|
fc.close()
|
|
|
|
if not filename:
|
|
print _('Field "CN" not found in the certificate!')
|
|
return 1
|
|
|
|
fd = open(cl_client_cert_dir + '/ca/' + filename, 'w')
|
|
fd.write(ca_root)
|
|
fd.close()
|
|
|
|
user_root_cert = cl_vars.Get('cl_user_root_cert')
|
|
user_root_cert = user_root_cert.replace("~", home_path)
|
|
fa = open(user_root_cert, 'a')
|
|
fa.write(ca_root)
|
|
fa.close()
|
|
print _("Certificate added")
|
|
else:
|
|
print _("file containing the CA certificate now exists")
|
|
return 0
|
|
|
|
|
|
def client_post_auth(client):
|
|
""" authorization client or post request """
|
|
sid = get_sid(client.SID_FILE)
|
|
try:
|
|
if os.path.exists(client.CERT_FILE):
|
|
pass # client_post_cert(client)
|
|
else:
|
|
# client_post_request(client)
|
|
print _('You do not have a certificate. Use option '
|
|
'--gen-cert-by HOST to generate a new certificate '
|
|
'or --get-cert-from HOST to get the certificate '
|
|
'from the server.')
|
|
sys.exit()
|
|
print client.service.versions(sid, VERSION)
|
|
except VerifyError, e:
|
|
print e.value
|
|
sys.exit()
|
|
|
|
|
|
# show rights on requested certificated
|
|
def cert_right_inf(client, sid, cert_id):
|
|
s = client.service.view_cert_right(cert_id)
|
|
if s[0][0] == "-1":
|
|
print _("Certificate not found on the server!")
|
|
return -1
|
|
if s[0][0] == "-2":
|
|
print _("Failed to create the certificate ID!")
|
|
return -2
|
|
if s[0][0] == "Permission denied":
|
|
print _("%s: Permission denied") % s[0][1]
|
|
return -3
|
|
|
|
print _("The certificate with ID = %d can execute:") % cert_id
|
|
for meth in s[0]:
|
|
print " - %s" % meth
|
|
|
|
|
|
# Viewing rights of any certificate on server by its id
|
|
def client_view_cert_right(client):
|
|
cert_id = raw_input(_("Certificate ID: "))
|
|
try:
|
|
cert_id = int(cert_id)
|
|
except ValueError:
|
|
print _("Invalid certificate ID")
|
|
return 1
|
|
try:
|
|
sid = get_sid(client.SID_FILE)
|
|
if cert_id > 0:
|
|
cert_right_inf(client, sid, cert_id)
|
|
else:
|
|
print _("Please enter a valid certificate ID!")
|
|
except Exception, e:
|
|
if e[0][0] == 403:
|
|
print _('Permission denied')
|
|
else:
|
|
print e
|
|
# print _("Failed to get data")
|
|
return 1
|
|
return 0
|