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/cl_client.py

630 lines
21 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.
from calculate.core.server.local_call import Display, Methods, has_force_arg
from calculate.lib.utils.tools import unpack_single_opts
import calculate.contrib
from suds import WebFault
from suds.transport import TransportError
from .client_class import Client_suds
import traceback as tb
import time
import logging
import os
import sys
import threading
import urllib.request as urllib2
from urllib.error import URLError
from .pid_information import client_list_methods
from .cert_func import (client_post_auth, client_post_request, client_get_cert,
client_post_cert, get_password_from_daemon,
clear_password)
from .sid_func import session_clean, client_session_info, client_session_list
from .cert_verify import get_CRL, VerifyError
import M2Crypto
import OpenSSL
from calculate.core.datavars import DataVarsCore
from .client_class import HTTPSClientCertTransport
from .methods_func import call_method, get_method_argparser, parse, get_view
from .function import (MessageReceiver, MessageDispatcher, clear, _print,
get_view_params, parse_error)
from calculate.lib.utils.files import makeDirectory, readLinesFile
from calculate.lib.cl_lang import setLocalTranslate
from M2Crypto import BIO
_ = lambda x: x
setLocalTranslate('cl_console3', sys.modules[__name__])
def get_message_receiver(client):
return MessageReceiver(client, MessageDispatcher(Methods()), Display())
def get_entire_message_receiver(client, pid):
return MessageReceiver.from_entire(client, pid,
MessageDispatcher(Methods()), Display())
def client_signal(client):
Vars = DataVarsCore()
Vars.importCore()
Vars.flIniFile()
try:
client_active = Vars.Get('core.cl_core_client_active_period')
except:
client_active = 15
while True:
sid = int(client.get_sid())
try:
client.service.active_client(sid)
except:
print(_('no connection to the server!'))
raise Exception(1)
time.sleep(float(client_active))
class StoppableThread(threading.Thread):
def __init__(self):
super().__init__()
self._thread_stopped = threading.Event()
self._pause = threading.Event()
self._paused = threading.Event()
def run(self):
l = ['|', '/', '-', '\\', '|', '/', '-', '\\']
while True:
for i in l:
sys.stdout.write("\r\r" + i)
sys.stdout.flush()
time.sleep(.1)
while self.paused() and not self.stopped():
self._paused.set()
if self.stopped():
sys.stdout.write("\b")
sys.stdout.flush()
return 0
def pause(self):
self._pause.set()
while not self._paused.is_set():
self._paused.clear()
sys.stdout.write("\r")
sys.stdout.flush()
def resume(self):
self._pause.clear()
def stop(self):
self._thread_stopped.set()
def stopped(self):
return self._thread_stopped.isSet()
def paused(self):
return self._pause.isSet()
def connect_with_cert(cert, path_to_cert, url, args, wait_thread, clVarsCore,
crypto_Error, Connect_Error):
flag_thread_start = False
cert_name = cert
CERT_FILE = os.path.join(path_to_cert, cert_name + '.crt')
CERT_KEY = os.path.join(path_to_cert, cert_name + '.key')
if not os.path.isfile(CERT_FILE) or not os.path.isfile(CERT_KEY):
Connect_Error = 1
return None, 1, crypto_Error, False, None
client = None
rsa_password = args.cert_passwd or ""
with open(CERT_KEY) as inf:
if 'ENCRYPTED' in inf.readline():
if not args.cert_passwd:
Connect_Error = 1
return None, 1, crypto_Error, False, _("RSA key contain ENCRYPTED. Use '--cert-passwd' to provide password")
try:
bio = M2Crypto.BIO.openfile(CERT_KEY)
rsa = M2Crypto.m2.rsa_read_key(bio._ptr(), lambda *unused: bytes(rsa_password, 'utf-8'))
except SystemError as e:
Connect_Error = 1
return None, 1, crypto_Error, False, _("Failed to read rsa key")
store_passwd = None
if not rsa:
try:
port = args.port or clVarsCore.Get('core.cl_core_port')
store_passwd = get_password_from_daemon(args.host, port, wait_thread)
except TypeError:
return None, 1, crypto_Error, False, _("Failed to get password from daemon or provided password is incorrect")
key_passwd = store_passwd
er = None
try:
ca_certs = os.path.join(path_to_cert, 'ca/ca_root.crt')
client = Client_suds(
url, transport=HTTPSClientCertTransport(
CERT_KEY, CERT_FILE, path_to_cert, password=key_passwd,
ca_certs=ca_certs, wait_thread=wait_thread, rsa_password=bytes(rsa_password, 'utf-8')))
if not wait_thread.is_alive():
wait_thread = StoppableThread()
flag_thread_start = True
wait_thread.start()
client.wsdl.services[0].setlocation(url)
client.set_parameters(path_to_cert, CERT_FILE, CERT_KEY, args.host)
wait_thread.stop()
client_post_cert(client, clVarsCore)
Connect_Error = 0
except VerifyError as e:
Connect_Error = 1
er = e
except OpenSSL.crypto.Error as e:
Connect_Error = 1
crypto_Error = 1
er = e
except URLError as e:
Connect_Error = 1
er = e
except Exception as e:
er = e
if e == 3:
wait_thread.stop()
sys.exit(1)
Connect_Error = 1
if flag_thread_start:
wait_thread.stop()
return (client, Connect_Error, crypto_Error,
True if store_passwd is not None else False, er)
def get_server_hostname(host, path_to_cert):
compliance_file = os.path.join(path_to_cert, 'compliance_server_names')
if not os.path.isfile(compliance_file):
fd = open(compliance_file, 'w')
fd.close()
for line in readLinesFile(compliance_file):
adress, server_hostname = line.split(' ', 1)
if adress == host:
return server_hostname
return None
def add_server_hostname(host, path_to_cert, server_hostname):
try:
compliance_file = os.path.join(path_to_cert, 'compliance_server_names')
if not os.path.isfile(compliance_file):
fd = open(compliance_file, 'w')
fd.close()
temp_file = ''
find_flag = False
for line in readLinesFile(compliance_file):
adress, temp_server_hostname = line.split(' ', 1)
if adress == host:
temp_file += "%s %s\n" % (adress, server_hostname)
find_flag = True
else:
temp_file += line + '\n'
if not find_flag:
temp_file += "%s %s\n" % (host, server_hostname)
fd = open(compliance_file, 'w')
fd.write(temp_file)
fd.close()
return True
except Exception as e:
print(e)
return False
def https_server(client, args, unknown_args, url, clVarsCore, wait_thread):
client_post_auth(client)
if args.stop_consoled:
wait_thread.stop()
os.system('cl-consoled --stop')
return 0
if args.session_clean:
wait_thread.stop()
session_clean(client)
if args.session_info or args.session_num_info:
wait_thread.stop()
client_session_info(client, args.session_num_info)
return 0
if args.session_list:
wait_thread.stop()
client_session_list(client)
return 0
if args.pid_res == "list":
from .pid_information import client_pid_info
wait_thread.stop()
client_pid_info(client, wait_thread)
return 0
try:
client.frame_period = clVarsCore.Get('core.cl_core_get_frame_period')
except:
client.frame_period = 2
if args.pid_res:
wait_thread.stop()
if not args.pid_res.isdigit():
print(_("Wrong PID"))
return 1
mr = get_entire_message_receiver(client, int(args.pid_res))
if mr:
mr.get_messages()
if not args.keep_result:
client.service.clear_pid_cache(client.sid, int(args.pid_res))
return 0
else:
return 1
if args.pid_kill:
wait_thread.stop()
from .pid_information import client_pid_kill
return client_pid_kill(client, args.pid_kill)
retCode = 0
if not args.method:
wait_thread.stop()
client_list_methods(client)
return 1
elif args.method and args.help:
# вычислить наличие флага --force
method_parser = None
try:
dispatch_usenew = has_force_arg(unknown_args)
while True:
view_params = get_view_params(client, args.method + '_view',
step=None, expert=True,
onlyhelp=True,
dispatch_usenew=dispatch_usenew)
view = get_view(client, args.method, client.sid, view_params)
method_parser = get_method_argparser(view, args)
_unknown_args = method_parser.fixBoolVariables(unknown_args)
_args, _unknown_args = method_parser.parse_known_args(
_unknown_args)
if dispatch_usenew == _args.no_questions:
break
else:
client.service.clear_method_cache(client.sid, args.method)
dispatch_usenew = _args.no_questions
finally:
wait_thread.stop()
# sys.stdout.write("\b")
# sys.stdout.flush()
client.service.clear_method_cache(client.sid, args.method)
method_parser.print_help()
else:
method_result = call_method(client, args, unknown_args, wait_thread)
mr = get_message_receiver(client)
if method_result:
client.no_progress = args.no_progress
try:
mr.analysis(method_result)
# analysis(client, client.sid, method_result)
except URLError as e:
_print(parse_error(e))
except KeyboardInterrupt:
try:
print()
mess = method_result[0][0]
pid = int(mess.message)
result = client.service.pid_kill(pid, client.sid)
if result in [0, 2]:
print(_('Process terminated'))
elif result == -1:
print(_("Certificate not found on the server"))
elif result == -2:
print(_("Session not matching your certificate"))
elif result == 1:
print(_("Failed to terminate the process"))
mr.analysis(method_result)
except Exception as e:
_print(parse_error(e))
try:
mess = method_result[0][0]
pid = int(mess.message)
except:
return 1
retCode = 1 if int(
client.service.pid_info(client.sid, pid)[0][1]) else 0
if not args.keep_result:
client.service.clear_pid_cache(client.sid, pid)
client.service.clear_method_cache(client.sid, args.method)
wait_thread.stop()
return retCode
def main(wait_thread):
parser = parse()
args, unknown_args = parser.parse_known_args(
list(unpack_single_opts(sys.argv[1:])))
wait_thread.start()
sym_link = os.path.basename(sys.argv[0])
if sym_link != 'cl-console':
import calculate.core.server.loaded_methods as loaded_methods
ob = DataVarsCore()
ob.importCore()
# set var env
if not ob.flIniFile():
sys.exit(1)
# cl_wsdl = ob.Get('cl_wsdl')
cl_wsdl = ob.Get('cl_wsdl_available')
# создать симлинки на команды
from calculate.core.server.func import initialization
initialization(cl_wsdl)
ob.close()
if sym_link in loaded_methods.LoadedMethods.conMethods.keys():
args.method = loaded_methods.LoadedMethods.conMethods[sym_link][0]
args.host = 'localhost'
if not args.method and args.help:
wait_thread.stop()
# sys.stdout.write('\r')
# sys.stdout.flush()
parser.print_help()
return 0
if not args.method:
if unknown_args:
wait_thread.stop()
# sys.stdout.write('\r')
# sys.stdout.flush()
args = parser.parse_args(
list(unpack_single_opts(sys.argv[1:])))
logging.basicConfig(level=logging.FATAL)
logging.getLogger('suds.client').setLevel(logging.FATAL)
logging.getLogger('suds.transport').setLevel(logging.FATAL)
logging.getLogger('suds.transport.http').setLevel(logging.FATAL)
logging.getLogger('suds.umx.typed').setLevel(logging.ERROR)
clVarsCore = DataVarsCore()
clVarsCore.importCore()
clVarsCore.flIniFile()
homePath = clVarsCore.Get('ur_home_path')
port = args.port or clVarsCore.GetInteger('core.cl_core_port')
host = args.host
path_to_cert = args.path_to_cert
if not path_to_cert:
path_to_cert = clVarsCore.Get('core.cl_client_cert_dir')
path_to_cert = path_to_cert.replace("~", homePath)
for dirs in ['', 'ca', 'trusted']:
dir_path = os.path.join(path_to_cert, dirs)
if not os.path.isdir(dir_path):
if not makeDirectory(dir_path):
wait_thread.stop()
sys.stdout.write('\r')
sys.stdout.flush()
print(_("Failed to create directory %s") % dir_path)
return 1
if args.update_crl:
wait_thread.stop()
getCRL = threading.Thread(target=get_CRL, args=(path_to_cert,))
getCRL.start()
getCRL.join()
print('CRL updated')
return 0
if args.by_host:
wait_thread.stop()
client_post_request(path_to_cert, args)
return 0
if args.from_host:
wait_thread.stop()
client_get_cert(path_to_cert, args)
return 0
url = "https://%s:%s/?wsdl" % (host, port)
try:
from calculate.lib.utils.dbus_tools import run_dbus_core
run_dbus_core(host, port)
except ImportError:
pass
clear()
serv_hostname = get_server_hostname(host, path_to_cert)
get_name_flag = False
client = None
if serv_hostname:
Connect_Error = 1
crypto_Error = 0
client, Connect_Error, crypto_Error, passwd_flag, e = \
connect_with_cert(serv_hostname, path_to_cert, url, args,
wait_thread, clVarsCore, crypto_Error,
Connect_Error)
if not wait_thread.is_alive():
wait_thread = StoppableThread()
wait_thread.start()
get_name_flag = True
if Connect_Error:
if crypto_Error and passwd_flag:
wait_thread.stop()
sys.stdout.write('\r')
sys.stdout.flush()
print(_('Invalid password'))
# delete password from daemon list
clear_password(host, port)
elif e:
wait_thread.stop()
if type(e) != int:
print(_('Error: '), e)
get_name_flag = False
if get_name_flag:
if client:
try:
client.port = port
return_val = 1
try:
return_val = https_server(client, args, unknown_args, url,
clVarsCore, wait_thread)
except URLError as e:
print(_('Error: '), e)
except KeyboardInterrupt:
wait_thread.stop()
red = '\n' + '\033[31m * \033[0m'
print(red + _("Manually interrupted"))
except Exception as e:
wait_thread.stop()
if type(e) != int:
if e:
print(e)
elif e.args:
print(e)
return 1
wait_thread.stop()
return return_val
except WebFault as f:
print(_("Exception: %s") % f)
_print(f.fault)
except TransportError as te:
print(_("Exception: %s") % te)
except KeyboardInterrupt:
wait_thread.stop()
red = '\n' + '\033[31m * \033[0m'
print(red + _("Manually interrupted"))
except Exception as e:
print(_("Exception: %s") % e)
tb.print_exc()
wait_thread.stop()
server_host_name = ""
try:
client = Client_suds(
url, transport=HTTPSClientCertTransport(None, None, path_to_cert))
client.wsdl.services[0].setlocation(url)
server_host_name = client.service.get_server_host_name()
if not add_server_hostname(host, path_to_cert, server_host_name):
print('compliance_file write error!')
del client
except URLError as e:
wait_thread.stop()
print('\b' + _('Failed to connect') + ':', e)
return 1
except KeyboardInterrupt:
wait_thread.stop()
red = '\n' + '\033[31m * \033[0m'
print(red + _("Manually interrupted"))
try:
import glob
all_cert_list = glob.glob(os.path.join(path_to_cert, '*.crt'))
fit_cert_list = []
for client_cert_path in all_cert_list:
client_cert = client_cert_path.replace(path_to_cert, '')
client_cert_name = client_cert.replace('.crt', '')
if server_host_name.endswith(client_cert_name):
fit_cert_list.append(client_cert_name)
fit_cert_list.sort(key=len)
Connect_Error = 1
crypto_Error = 0
e = None
passwd_flag = False
for i in range(0, len(fit_cert_list)):
cert_name = fit_cert_list.pop()
client, Connect_Error, crypto_Error, passwd_flag, e = \
connect_with_cert(cert_name, path_to_cert, url, args,
wait_thread, clVarsCore, crypto_Error,
Connect_Error)
if not wait_thread.is_alive():
wait_thread = StoppableThread()
wait_thread.start()
if Connect_Error == 0:
break
# If the certificate file misses
if Connect_Error:
if crypto_Error and passwd_flag:
wait_thread.stop()
# sys.stdout.write('\r')
# sys.stdout.flush()
print(_('Invalid password'))
# delete password from daemon list
clear_password(host, port)
return 1
elif e:
wait_thread.stop()
if type(e) != int:
print(_('Error: '), e)
return 1
CERT_FILE = None
CERT_KEY = None
client = Client_suds(
url, transport=HTTPSClientCertTransport(CERT_KEY, CERT_FILE,
path_to_cert))
client.wsdl.services[0].setlocation(url)
client.set_parameters(path_to_cert, CERT_FILE, CERT_KEY, args.host)
client.port = port
return_val = 1
try:
return_val = https_server(client, args, unknown_args, url,
clVarsCore, wait_thread)
except URLError as e:
print(_('Error: '), e)
except KeyboardInterrupt:
wait_thread.stop()
red = '\n' + '\033[31m * \033[0m'
print(red + _("Manually interrupted"))
except Exception as e:
wait_thread.stop()
if type(e) != int:
if e:
print(e)
elif e.args:
print(e)
# tb.print_exc()
return 1
wait_thread.stop()
return return_val
# ----------------------------------------------------
except WebFault as f:
print(_("Exception: %s") % f)
_print(f.fault)
except TransportError as te:
print(_("Exception: %s") % te)
except KeyboardInterrupt:
wait_thread.stop()
red = '\n' + '\033[31m * \033[0m'
print(red + _("Manually interrupted"))
except Exception as e:
print(_("Exception: %s") % e)
tb.print_exc()
wait_thread.stop()