#-*- 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 .. import qt import calculate.contrib from suds import WebFault import logging, OpenSSL import os import calculate.lib.configparser as ConfigParser import urllib.request as urllib2 import getpass # from calculate.core.client.function import clear as clear_suds_cache from .utils import clear as clear_suds_cache from .session_function import client_post_cert # from calculate.core.client.cert_verify import VerifyError from .client_class import VerifyError from .client_class import Client_suds, HTTPSClientCertTransport from .more import post_connect_action, show_msg, uniq, LabelWordWrap, get_icon, dpivalue class LocalhostPasswd(qt.QDialog): def __init__(self, parent): super().__init__() grid = qt.QGridLayout(self) grid.setContentsMargins(10, 10, 10, 10) grid.setSpacing(4) self.lbl_passwd = qt.QLabel(_("Password"), self) self.text_passwd = qt.QLineEdit('', self) self.text_passwd.setEchoMode(self.text_passwd.Password) grid.addWidget(self.lbl_passwd, 0, 0) grid.addWidget(self.text_passwd, 0, 1) layout_button = qt.QHBoxLayout() self.cmd_ok = qt.QPushButton(_('Ok'), self) self.cmd_ok.setDefault(True) self.cmd_ok.setAutoDefault(True) self.cmd_ok.clicked.connect(self.set_disabled) self.cmd_ok.clicked.connect(self.onClick) self.cmd_ok.setFixedWidth(100) self.cmd_cancel = qt.QPushButton(_('Cancel'), self) self.cmd_cancel.setShortcut(qt.QKeySequence(qt.Qt.Key_Escape)) self.cmd_cancel.clicked.connect(self.close) self.cmd_cancel.setFixedWidth(100) layout_button.addWidget(self.cmd_ok) layout_button.addWidget(self.cmd_cancel) grid.addLayout(layout_button, 1,0,1,2, qt.Qt.AlignRight) self.setLayout(grid) self.setFixedSize(self.sizeHint()) self._text = None self.exec_() def onClick(self): self._text = self.text_passwd.text() self.close() def set_disabled(self): self.cmd_ok.setDisabled(True) def text(self): return self._text class FrameConnection(qt.QWidget): def __init__(self, parent, ClientObj): super().__init__() self.ClientObj = ClientObj def initUI(self, parent, window): grid = qt.QGridLayout(self) grid.setContentsMargins(10, 10, 10, 10) grid.setSpacing(2) self.lbl_host = LabelWordWrap(_("Host"), self) self.lbl_port = LabelWordWrap(_("Port"), self) self.lbl_passwd = LabelWordWrap(_("Password"), self) self.text_host = qt.QLineEdit(self.ClientObj.default_host, self) self.text_port = qt.QLineEdit(self.ClientObj.default_port, self) self.text_passwd = qt.QLineEdit('', self) self.text_passwd.setEchoMode(self.text_passwd.Password) ###################### # add completer in 'host name' QLineEdit def add_wordlist(self): def wrapper(): self.wordList.append (self.text_host.text()) self.wordList = uniq(self.wordList) del (self.completer) self.completer = qt.QCompleter(self.wordList, self) self.completer.setCaseSensitivity(qt.Qt.CaseInsensitive) self.completer.setMaxVisibleItems(7) self.text_host.setCompleter(self.completer) return wrapper config = ConfigParser.ConfigParser() config.read(self.ClientObj.user_config) try: wordList = config.get('other', 'connect_list') self.wordList = wordList.split(',') except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): self.wordList = [] self.completer = qt.QCompleter(self.wordList, self) self.completer.setCaseSensitivity(qt.Qt.CaseInsensitive) self.completer.setMaxVisibleItems(7) self.text_host.setCompleter(self.completer) self.text_host.editingFinished.connect(add_wordlist(self)) ##################### grid.addWidget(self.lbl_host, 0, 0) grid.addWidget(self.lbl_port, 1, 0) grid.addWidget(self.text_host, 0, 1) grid.addWidget(self.text_port, 1, 1) grid.addWidget(self.lbl_passwd, 2, 0) grid.addWidget(self.text_passwd, 2, 1) self.cmd_connect = qt.QPushButton(_('Connect'), self) self.cmd_connect.setIcon(get_icon("network-connect")) self.cmd_connect.setDefault(True) self.cmd_connect.setAutoDefault(True) # self.cmd_connect.setMaximumWidth(120) self.cmd_connect.setShortcut(qt.QKeySequence(qt.Qt.Key_Return)) self.cmd_cancel = qt.QPushButton(_('Cancel'), self) # self.cmd_cancel.setMaximumWidth(120) self.cmd_cancel.setShortcut(qt.QKeySequence(qt.Qt.Key_Escape)) self.cmd_cancel.clicked.connect(self.close) layout_button = qt.QHBoxLayout() layout_button.addWidget(self.cmd_connect) layout_button.addWidget(self.cmd_cancel) grid.addLayout(layout_button, 3, 0, 1, 2) grid.setColumnStretch(0,1) grid.setColumnStretch(1,5) self.cmd_connect.clicked.connect (self.set_disabled) self.cmd_connect.clicked.connect (self.onClick) # for clear memory after closed this window self.setAttribute(qt.Qt.WA_DeleteOnClose) self.setLayout(grid) self.setFixedSize(dpivalue(300), dpivalue(160)) self.move(window.geometry().x() + window.geometry().width() / 2 \ - self.sizeHint().width() / 2, \ window.geometry().y() + window.geometry().height() / 2 \ - self.sizeHint().height() / 2) self.setWindowTitle(_('Connection')) self.setWindowIcon(get_icon("network-connect")) def set_disabled(self): self.setDisabled(True) self.ClientObj.app.processEvents() # establish a connection def onClick(self): # print "DEBUG: onClick" self.setDisabled(True) if self.ClientObj.client: show_msg(_('You are connected to the server!')+'\n' + \ _("Please disconnect") +' '+ _('previous connection!'), \ _('Connection Error')) return 1 self.ClientObj.app.processEvents() self.setDisabled(False) # write parameters self.str_host = self.text_host.text() self.str_port = self.text_port.text() self.str_passwd = self.text_passwd.text() # add host_name in list ########## start while len(self.wordList) > 6: self.wordList.remove(self.wordList[6]) if not self.str_host in self.wordList: self.wordList.insert(0, self.str_host) if not os.path.isfile (self.ClientObj.user_config): f = open (self.ClientObj.user_config, 'w') f.close() fc = open (self.ClientObj.user_config, 'r') config = fc.readlines() fc.close() new_config = [] host_list_flag = False for line in config: if line.startswith('connect_list '): host_list_flag = True new_config.append('connect_list = %s\n' \ %','.join(self.wordList)) else: new_config.append(line) if not host_list_flag: part_flag = False temp_cfg = [] for line in new_config: temp_cfg.append(line) #add new line in config if line.startswith('[other]'): temp_cfg.append('%s = %s\n' \ %('connect_list', ','.join(self.wordList))) part_flag = True new_config = temp_cfg # if part not exists if not part_flag: new_config.append('\n') new_config.append('%s\n' %'[other]') new_config.append('%s = %s\n' \ %('connect_list', ','.join(self.wordList))) fnc = open(self.ClientObj.user_config, 'w') for line in new_config: fnc.write(line) fnc.close() # add host_name in list ########## end try: int_port = int(self.str_port) except: show_msg(_("Enter the port correctly!")) return 1 self.connect_to_host(self.str_host, int_port) def connect_to_host(self, host_name, port = None, auto = False, re_passwd = False): 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) clear_suds_cache() # not twice connect to localhost if host_name == 'localhost': host_name = '127.0.0.1' # raise Exception if not port: port = self.ClientObj.VarsApi.GetInteger('core.cl_core_port') if hasattr (self.ClientObj._parent, 'find_host'): if self.ClientObj._parent.find_host(host_name, port): self.close() return # get server hostname url = "https://%s:%d/?wsdl" %(host_name, port) self.ClientObj.port = port _print (url) try: from calculate.lib.utils.dbus_tools import run_dbus_core run_dbus_core(host_name, port) except ImportError: pass path_to_cert = self.ClientObj.path_to_cert try: client = Client_suds(url, transport = HTTPSClientCertTransport(None, None, path_to_cert, parent = self.ClientObj, timeout = 10)) except AttributeError as e: show_msg (_('This server is not trusted'), _('Not connected!')) return 1 except Exception as e: show_msg (e, _("Not connected!")) return 1 client.wsdl.services[0].setlocation(url) try: server_host_name = client.service.get_server_host_name() except urllib2.URLError as e: show_msg (e, _("Not connected!")) return 1 except Exception as e: _print ('connect_to_host Exception: ', e) return 1 del (client) if not hasattr (self, 'str_passwd'): self.str_passwd = None else: passwd = None try: import glob all_cert_list = glob.glob(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 for i in range (0, len(fit_cert_list)): cert_name = fit_cert_list.pop() CERT_FILE = path_to_cert + cert_name + '.crt' CERT_KEY = path_to_cert + cert_name + '.key' # check passwd private_key import M2Crypto bio = M2Crypto.BIO.openfile(CERT_KEY) rsa = M2Crypto.m2.rsa_read_key(bio._ptr(), lambda *unused: b"") if re_passwd != False: self.str_passwd = re_passwd#, "UTF-8" if not rsa and not self.str_passwd and auto: self.passwd_wgt = LocalhostPasswd(self) passwd = self.passwd_wgt.text() self.str_passwd = passwd if passwd else None try: # if True: passw = bytes(self.str_passwd, "UTF-8") if self.str_passwd else None self.ClientObj.client = Client_suds(url,\ transport = HTTPSClientCertTransport(CERT_KEY, \ CERT_FILE, path_to_cert, parent = self.ClientObj, \ timeout = 5, password = passw)) self.ClientObj.client.wsdl.services[0].setlocation(url) self.ClientObj.client.set_parameters \ (path_to_cert, CERT_FILE, CERT_KEY) self.ClientObj.client.server_host_name = host_name client_post_cert(self.ClientObj.client, \ self.ClientObj.lang) Connect_Error = 0 except VerifyError as e: show_msg (e.value,_("Server certificate verification error"),self) e = 'VerifyError' Connect_Error = 1 except OpenSSL.crypto.Error as e: print("OPENSSL ERROR") Connect_Error = 1 crypto_Error = 1 # except Exception as e: # print("GENERAL ERROR") # print(e) # Connect_Error = 1 if Connect_Error == 0: break #If the certificate file misses if Connect_Error: self.ClientObj.client = None if crypto_Error and 'passwd' in locals(): show_msg (_('Invalid password'), \ _('Connection Error'), self) return # self.close() if 'e' not in locals(): mess = _('You do not have a certificate. Please generate ' 'a new request and get the new certificate from ' 'the server.') if host_name in ("127.0.0.1", "localhost"): mess = ("%s %s:\ncl-core -u %s")%(mess, _("Also you can generate administrator certificate by root command"), getpass.getuser()) show_msg (mess, parent = self) elif e == 'VerifyError': pass elif e == 1: mess = _('You do not have a certificate or your ' 'certificate does not match the server certificate.' ' Please generate a new request and get the new ' 'certificate from the server.') if host_name in ("127.0.0.1", "localhost"): mess = ("%s %s:\ncl-core -u %s")%(mess, _("Also you can generate administrator certificate by root command"), getpass.getuser()) show_msg (mess, parent = self) else: if e or e.args: show_msg (e, parent = self) return CERT_FILE = None CERT_KEY = None self.ClientObj.client = Client_suds(url,\ transport = HTTPSClientCertTransport(CERT_KEY, CERT_FILE,\ path_to_cert, parent = self.ClientObj, timeout = 5)) self.ClientObj.client.wsdl.services[0].setlocation(url) self.ClientObj.client.set_parameters (path_to_cert, CERT_FILE,\ CERT_KEY) try: self.ClientObj.client.frame_period = \ int(self.ClientObj.VarsApi.Get \ ('core.cl_core_get_frame_period')) except: self.ClientObj.client.frame_period = 2 self.ClientObj.host_name = host_name if CERT_FILE: if hasattr (self.ClientObj._parent, 'rename_tab'): self.ClientObj._parent.rename_tab(host_name) if host_name in ['127.0.0.1', 'localhost']: self.ClientObj._parent.set_localhost(self.ClientObj) self.ClientObj.client.server_host_name = host_name self.ClientObj.client.password = self.str_passwd # self.ClientObj._parent.connect_count_changed(1) post_connect_action(self.ClientObj.client, self.ClientObj) #---------------------------------------------------- except WebFault as f: show_msg ("Exception: %s" %f) _print (f.fault) self.close()