#-*- 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 .utils import clear as clear_suds_cache from .session_function import client_post_cert 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 from M2Crypto import BIO 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()