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-console/pym/console/application/cert_func.py

504 lines
16 KiB

8 years ago
# -*- 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.
8 years ago
import os
import pwd
import sys
import subprocess
import socket
import time
import urllib2
8 years ago
from calculate.console.application.function import _print
from function import get_ip_mac_type
from calculate.console.application.sid_func import get_sid
8 years ago
import OpenSSL
import hashlib
from client_class import HTTPSClientCertTransport
from cert_verify import VerifyError
from calculate.core.datavars import DataVarsCore
from calculate.core.server.methods_func import get_password
from calculate.lib.cl_lang import setLocalTranslate
from calculate.lib.utils.common import getpass
from calculate.lib.utils.files import listDirectory
8 years ago
_ = lambda x: x
setLocalTranslate('cl_console3', sys.modules[__name__])
VERSION = 0.11
8 years ago
def client_post_cert(client, clVars, show_info=False):
""" send a certificate server for check """
sid = get_sid(client.SID_FILE)
8 years ago
lang = os.environ['LANG'][:2]
_result_post_cert, _result_sid = client.service.init_session(sid, lang)
result_post_cert = _result_post_cert[1].integer
result_sid = _result_sid[1].integer
if os.environ.get("DEBUG"):
8 years ago
print _("The client uses certificate %s (server ID %s)") % (
client.CERT_FILE, result_post_cert[0])
if result_post_cert[0] == -4:
12 years ago
print _("Certificate not found on the server")
8 years ago
print _("the client uses certificate %s") % client.CERT_FILE
print _('You can generate a new certificate '
'using options --gen-cert-by and '
12 years ago
'--get-cert-from')
raise Exception(3)
8 years ago
# client_sid(sid, client, cert_id = results[0][0], clVars = clVars)
if result_post_cert[0] == -3:
12 years ago
print _("Certificate not sent!")
elif result_post_cert[0] == -2:
12 years ago
print _("Using the upstream certificate")
else:
if show_info:
8 years ago
print _(" Your certifitate ID = %d") % (result_post_cert[0])
try:
if result_post_cert[1] == -2:
12 years ago
print _("The certificate has expired")
elif result_post_cert[1] > 0:
if show_info:
12 years ago
print _("The certificate expires after %d days") \
8 years ago
% (result_post_cert[1])
except:
pass
# work with sid
fi = open(client.SID_FILE, 'w')
sid = str(result_sid[0])
fi.write(sid)
fi.close()
if show_info:
if result_sid[1] == 1:
print _(" New Session")
8 years ago
else:
print _(" Old Session")
print _(" Your session ID = %s") % sid
# Creation of secret key of the client
def new_key_req(key, cert_path, server_host_name, private_key_passwd=None,
auto=False):
from create_cert import generateRSAKey, makePKey, makeRequest, \
passphrase_callback
rsa = generateRSAKey()
8 years ago
rsa.save_key(key + '_pub', cipher=None, callback=lambda *unused: None)
pkey = makePKey(rsa)
if not passphrase_callback(private_key_passwd):
8 years ago
pkey.save_key(key, cipher=None, callback=lambda *unused: None)
else:
8 years ago
pkey.save_key(key, callback=lambda *unused: str(private_key_passwd))
12 years ago
req = makeRequest(rsa, pkey, server_host_name, auto)
crtreq = req.as_pem()
12 years ago
8 years ago
req_file = cert_path + '/%s.csr' % server_host_name
crtfile = open(req_file, 'w')
crtfile.write(crtreq)
crtfile.close()
12 years ago
user_name = pwd.getpwuid(os.getuid()).pw_name
try:
pwdObj = pwd.getpwnam(user_name)
except KeyError, e:
8 years ago
_print(e)
12 years ago
return None
os.chown(key, pwdObj.pw_uid, pwdObj.pw_gid)
os.chmod(key, 0600)
return req_file
8 years ago
def delete_old_cert(client):
try:
os.unlink(client.CERT_FILE)
os.unlink(client.REQ_FILE)
os.unlink(client.PKEY_FILE)
os.unlink(client.PubKEY_FILE)
except OSError, e:
8 years ago
_print(e.message)
8 years ago
def client_post_request(cert_path, args):
if os.path.exists(cert_path + 'req_id'):
12 years ago
print \
12 years ago
_("You already sent a certificate signature request.")
8 years ago
_print(_("Request ID = %s") % open(cert_path + 'req_id', 'r').read())
ans = raw_input(_("Send a new request? y/[n]: "))
if not ans.lower() in ['y', 'yes']:
return 0
clVars = DataVarsCore()
clVars.importCore()
clVars.flIniFile()
port = args.port or clVars.Get('core.cl_core_port')
8 years ago
url = "https://%s:%s/?wsdl" % (args.by_host, port)
print '%s\n' % url, _("connecting...")
from client_class import Client_suds
8 years ago
try:
8 years ago
client = Client_suds(url, transport=HTTPSClientCertTransport \
(None, None, cert_path))
except (KeyboardInterrupt, urllib2.URLError), e:
8 years ago
print '\n' + _("Closing. Connection error.")
_print(_("Error: %s") % e)
return 0
client.wsdl.services[0].setlocation(url)
8 years ago
server_host_name = client.service.get_server_host_name()
8 years ago
12 years ago
key = os.path.join(cert_path, server_host_name + '.key')
8 years ago
csr_file = os.path.join(cert_path, server_host_name + '.csr')
if os.path.exists(key) and os.path.exists(csr_file):
12 years ago
print _("the private key and request now exist")
12 years ago
ask = raw_input(_("Create a new private key and request? y/[n]: "))
8 years ago
if ask.lower() in ['y', 'yes']:
passwd = get_password()
8 years ago
new_key_req(key, cert_path, server_host_name,
private_key_passwd=passwd)
else:
passwd = get_password()
new_key_req(key, cert_path, server_host_name,
8 years ago
private_key_passwd=passwd)
ip, mac, client_type = get_ip_mac_type()
data = open(csr_file).read()
8 years ago
res = client.service.post_client_request(request=data, ip=ip,
mac=mac, client_type=client_type)
if int(res) < 0:
12 years ago
print _("The server has not signed the certificate!")
return 1
12 years ago
fc = open(os.path.join(cert_path, 'req_id'), 'w')
fc.write(res)
fc.close()
8 years ago
_print(_("Your request ID = %s") % res + '.\n',
_("To submit the certificate request on the server use command") + \
'\n' + 'cl-core --sign-client ID_CLIENT_REQUEST')
return 0
8 years ago
def client_get_cert(cert_path, args):
clVars = DataVarsCore()
clVars.importCore()
clVars.flIniFile()
12 years ago
if not os.path.exists(os.path.join(cert_path, 'req_id')):
12 years ago
print _("Request not sent or file %s deleted") \
8 years ago
% (os.path.join(cert_path, 'req_id'))
return 1
12 years ago
fc = open(os.path.join(cert_path, 'req_id'), 'r')
req_id = fc.read()
fc.close()
port = args.port or clVars.Get('core.cl_core_port')
8 years ago
url = "https://%s:%s/?wsdl" % (args.from_host, port)
print '%s\n' % url, _("connecting...")
from client_class import Client_suds
8 years ago
try:
8 years ago
client = Client_suds(url,
transport=HTTPSClientCertTransport(None, None,
cert_path))
except KeyboardInterrupt:
12 years ago
print _("Closing. Connection error.")
8 years ago
return 1
client.wsdl.services[0].setlocation(url)
8 years ago
server_host_name = client.service.get_server_host_name()
8 years ago
12 years ago
if not os.path.exists(os.path.join(cert_path, server_host_name + '.csr')):
12 years ago
print _("Request %s not found on the client's side") \
8 years ago
% (os.path.join(cert_path, server_host_name + '.csr'))
return 1
12 years ago
request = open(os.path.join(cert_path, server_host_name + '.csr')).read()
md5 = hashlib.md5()
md5.update(request)
md5sum = md5.hexdigest()
8 years ago
result = client.service.get_client_cert(req_id, md5sum)
cert = result[0][0]
12 years ago
try:
ca_root = result[0][1]
except IndexError:
ca_root = None
if cert == '1':
12 years ago
print _("Signature request rejected!")
return 1
elif cert == '2':
12 years ago
print _("Signature request not examined yet.")
8 years ago
print _("Your request ID = %s") % req_id + '.\n', \
_("To submit the certificate request on the server use command") + \
'\n' + 'cl-core --sign-client ID_CLIENT_REQUEST'
return 1
elif cert == '3':
12 years ago
print _("Request or signature not matching earlier data.")
return 1
elif cert == '4':
12 years ago
print _("The request was sent from another IP.")
return 1
12 years ago
cert_file = os.path.join(cert_path, server_host_name + '.crt')
fc = open(cert_file, 'w')
fc.write(cert)
fc.close()
try:
os.unlink(cert_path + 'req_id')
except OSError, e:
8 years ago
_print(e.message)
print _('Certificate saved. Your certificate ID: %s') % req_id
12 years ago
user_name = pwd.getpwuid(os.getuid()).pw_name
try:
pwdObj = pwd.getpwnam(user_name)
except KeyError, e:
8 years ago
_print(e)
12 years ago
return None
os.chown(cert_file, pwdObj.pw_uid, pwdObj.pw_gid)
os.chmod(cert_file, 0600)
if ca_root:
system_ca_db = clVars.Get('core.cl_glob_root_cert')
if os.path.exists(system_ca_db):
if ca_root in open(system_ca_db, 'r').read():
return 0
cl_client_cert_dir = clVars.Get('core.cl_client_cert_dir')
homePath = clVars.Get('ur_home_path')
8 years ago
cl_client_cert_dir = cl_client_cert_dir.replace("~", homePath)
12 years ago
root_cert_md5 = os.path.join(cl_client_cert_dir, "ca/cert_list")
md5 = hashlib.md5()
md5.update(ca_root)
md5sum = md5.hexdigest()
print "\n================================================="
print "md5sum = ", md5sum
if not os.path.exists(root_cert_md5):
8 years ago
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
8 years ago
words = line.split(' ', 1)
if words[0] == md5sum:
filename = words[1]
if not filename:
certobj = OpenSSL.crypto.load_certificate \
8 years ago
(OpenSSL.SSL.FILETYPE_PEM, ca_root)
Issuer = certobj.get_issuer().get_components()
for item in Issuer:
if item[0] == 'CN':
filename = item[1]
8 years ago
fc = open(root_cert_md5, "a")
fc.write('%s %s\n' % (md5sum, filename))
fc.close()
8 years ago
if not filename:
12 years ago
print _('Field "CN" not found in the certificate!')
return 1
8 years ago
12 years ago
fd = open(os.path.join(cl_client_cert_dir, 'ca', filename), 'w')
fd.write(ca_root)
fd.close()
8 years ago
user_root_cert = clVars.Get('core.cl_user_root_cert')
8 years ago
user_root_cert = user_root_cert.replace("~", homePath)
fa = open(user_root_cert, 'a')
fa.write(ca_root)
fa.close()
print _("filename = "), filename
12 years ago
print _("Certificate added")
else:
12 years ago
print _("The file containing the CA certificate now exists")
return 0
8 years ago
def client_post_auth(client):
""" authorization client or post request """
sid = get_sid(client.SID_FILE)
client.sid = int(sid)
try:
if os.path.exists(client.CERT_FILE):
8 years ago
pass # client_post_cert(client)
else:
8 years ago
# client_post_request(client)
print _(
"You do not have a certificate. Use option --gen-cert-by HOST to generate a new request or --get-cert-from HOST to get a new certificate from the server.")
12 years ago
raise Exception(1)
8 years ago
# print client.service.versions(sid, VERSION)
except VerifyError, e:
print e.value
12 years ago
raise Exception(1)
8 years ago
########## Get password
def getRunProc():
"""List run program"""
8 years ago
def getCmd(procNum):
8 years ago
cmdLineFile = '/proc/%s/cmdline' % procNum
try:
if os.path.exists(cmdLineFile):
8 years ago
return [open(cmdLineFile, 'r').read().strip(), procNum]
except:
pass
return ["", procNum]
8 years ago
if not os.access('/proc', os.R_OK):
return []
return map(getCmd,
8 years ago
filter(lambda x: x.isdigit(),
listDirectory('/proc')))
def owner(pid):
UID = 1
8 years ago
for ln in open('/proc/%s/status' % pid):
if ln.startswith('Uid:'):
uid = int(ln.split()[UID])
return pwd.getpwuid(uid).pw_name
8 years ago
def create_socket(file_path, username):
8 years ago
host = '' # ip
port = 5501 # порт
find_proc = False
8 years ago
# if not file_path:
# home_path = pwd.getpwuid(os.getuid()).pw_dir
# file_path = os.path.join(home_path, '.calculate', 'passwd_daemon')
# if not username:
# username = pwd.getpwuid(os.getuid()).pw_name
for run_commands in filter(lambda x: 'cl-consoled' in \
x[0], getRunProc()):
if 'python' in run_commands[0]:
if username == owner(run_commands[1]):
8 years ago
# print 'YES'
find_proc = True
if not find_proc:
try:
os.unlink(file_path)
except OSError, e:
8 years ago
_print(e.message)
cmd = ['cl-consoled']
8 years ago
# print cmd
subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
while True:
try:
8 years ago
s.bind((host, port)) # ассоциировать адрес с сокетом
break
except socket.error:
port += 1
return s
8 years ago
def set_password(s, req, size):
password = getpass.getpass(_('Password: '))
8 years ago
msg = '%s,%s' % (req, password)
s.send(msg)
resp = s.recv(size)
if resp.startswith('Error'):
8 years ago
_print(resp)
return password
8 years ago
def clear_password(server_host, server_port):
size = 1024 # размер данных
username = pwd.getpwuid(os.getuid()).pw_name
home_path = pwd.getpwuid(os.getuid()).pw_dir
file_path = os.path.join(home_path, '.calculate', 'passwd_daemon')
s = create_socket(file_path, username)
connect_error = 0
while connect_error < 16:
try:
while connect_error < 10:
if os.path.isfile(file_path):
serv_port, hash_val = open(file_path, 'r').read().split()
8 years ago
s.connect(('localhost', int(serv_port)))
req = 'delete,%s,%s,%s,%s' % (server_host, str(server_port),
username, hash_val)
s.send(req)
s.recv(size)
return
else:
connect_error += 1
time.sleep(0.3)
break
except socket.error:
time.sleep(0.3)
8 years ago
def socket_connect(s, file_path):
connect_error = 0
while connect_error < 16:
try:
while connect_error < 10:
if os.path.isfile(file_path):
serv_port, hash_val = open(file_path, 'r').read().split()
8 years ago
s.connect(('localhost', int(serv_port)))
return s, hash_val
else:
connect_error += 1
time.sleep(0.3)
break
except socket.error:
time.sleep(0.3)
8 years ago
def get_password_from_daemon(server_host, server_port, wait_thread):
size = 1024 # размер данных
username = pwd.getpwuid(os.getuid()).pw_name
home_path = pwd.getpwuid(os.getuid()).pw_dir
file_path = os.path.join(home_path, '.calculate', 'passwd_daemon')
while True:
s = create_socket(file_path, username)
s, hash_val = socket_connect(s, file_path)
8 years ago
req = '%s,%s,%s,%s' % (
server_host, str(server_port), username, hash_val)
s.send(req)
resp = s.recv(size)
if resp.startswith('Error'):
if 'timeout' in resp:
continue
wait_thread.stop()
sys.stdout.write('\r')
sys.stdout.flush()
password = set_password(s, req, size)
else:
password = resp if resp else None
return password