From 6b58e71c6ca08956e50212a1126bb41c4225045f Mon Sep 17 00:00:00 2001 From: fluzzi Date: Thu, 17 Mar 2022 19:05:23 -0300 Subject: [PATCH] first commit --- conn/__init__.py | 7 ++ conn/configfile.py | 55 ++++++++++++++ conn/core.py | 182 +++++++++++++++++++++++++++++++++++++++++++++ conn/tools.py | 25 +++++++ test.py | 7 ++ test.txt | 7 ++ 6 files changed, 283 insertions(+) create mode 100644 conn/__init__.py create mode 100755 conn/configfile.py create mode 100755 conn/core.py create mode 100755 conn/tools.py create mode 100755 test.py create mode 100644 test.txt diff --git a/conn/__init__.py b/conn/__init__.py new file mode 100644 index 0000000..773c8e7 --- /dev/null +++ b/conn/__init__.py @@ -0,0 +1,7 @@ +from conn.core import node +from conn.configfile import configfile +import conn.tools + +__version__ = "2.0" +__all__ = [node, configfile, tools] + diff --git a/conn/configfile.py b/conn/configfile.py new file mode 100755 index 0000000..702a136 --- /dev/null +++ b/conn/configfile.py @@ -0,0 +1,55 @@ +#!/usr/bin/python3 +#Imports +import yaml +import os +import re +from . import tools +from Crypto.PublicKey import RSA + + +#Constants + +#Variables + +#functions and clsses + +class configfile: + + def __init__(self, conf = None): + home = os.path.expanduser("~") + self.defaultdir = home + '/.config/conn' + self.defaultfile = self.defaultdir + '/config.yaml' + self.defaultkey = self.defaultdir + '/.osk' + if conf == None: + self.dir = self.defaultdir + self.file = self.defaultfile + else: + self.dir = os.path.dirname(conf) + self.file = conf + if os.path.exists(self.file): + config = self.loadconfig(self.file) + else: + config = self.createconfig(self.file) + self.config = config["config"] + self.connections = config["connections"] + self.profiles = config["profiles"] + + + def loadconfig(self, conf): + ymlconf = open(conf) + return yaml.load(ymlconf.read(), Loader=yaml.FullLoader) + + def createconfig(self, conf): + defaultconfig = {'config': {'case': False, 'frun': False, 'idletime': 30}, 'connections': {}, 'profiles': {}} + if not os.path.exists(conf): + with open(conf, "w") as f: + yaml.dump(defaultconfig, f, explicit_start=True) + f.close() + ymlconf = open(conf) + return yaml.load(ymlconf.read(), Loader=yaml.FullLoader) + + def createkey(self, keyfile): + key = RSA.generate(2048) + with open('mykey.pem','wb') as f: + f.write(key.export_key('PEM')) + f.close() diff --git a/conn/core.py b/conn/core.py new file mode 100755 index 0000000..97f04c6 --- /dev/null +++ b/conn/core.py @@ -0,0 +1,182 @@ +#!/usr/bin/python3 +#Imports +import yaml +import os +import re +import pexpect +from Crypto.PublicKey import RSA +from Crypto.Cipher import PKCS1_OAEP +import ast +from time import sleep +import datetime +import sys +from conn import tools +from .configfile import configfile + +#Constants + +#Variables + +#functions and clsses + +class node: + def __init__(self, unique, host, options='', logs='', password='', port='', protocol='', type='', user=''): + try: + config = configfile() + self.idletime = config.config["idletime"] + except: + config = {} + self.idletime = 0 + self.unique = unique + self.id = self.unique.split("@")[0] + attr = {"host": host, "logs": logs, "options":options, "port": port, "protocol": protocol, "user": user} + for key in attr: + profile = re.search("^@(.*)", attr[key]) + if profile: + setattr(self,key,config.profiles[profile.group(1)][key]) + elif attr[key] == '' and key == "protocol": + try: + setattr(self,key,config.profiles["default"][key]) + except: + setattr(self,key,"ssh") + else: + setattr(self,key,attr[key]) + if isinstance(password,list): + self.password = [] + for i, s in enumerate(password): + profile = re.search("^@(.*)", password[i]) + if profile: + self.password.append(config.profiles[profile.group(1)]["password"]) + else: + self.password = [str(password)] + + def __passtx(self, passwords, *, keyfile=None): + if keyfile is None: + home = os.path.expanduser("~") + keyfile = home + '/.config/conn/.osk' + key = RSA.import_key(open(keyfile).read()) + publickey = key.publickey() + encryptor = PKCS1_OAEP.new(publickey) + decryptor = PKCS1_OAEP.new(key) + dpass = [] + for passwd in passwords: + decrypted = decryptor.decrypt(ast.literal_eval(str(passwd))).decode("utf-8") + dpass.append(decrypted) + return dpass + + + + def _logfile(self, logfile = None): + if logfile == None: + logfile = self.logs + logfile = logfile.replace("${id}", self.id) + logfile = logfile.replace("${unique}", self.unique) + logfile = logfile.replace("${host}", self.host) + logfile = logfile.replace("${port}", self.port) + logfile = logfile.replace("${user}", self.user) + logfile = logfile.replace("${protocol}", self.protocol) + now = datetime.datetime.now() + dateconf = re.search(r'\$\{date \'(.*)\'}', logfile) + if dateconf: + logfile = re.sub(r'\$\{date (.*)}',now.strftime(dateconf.group(1)), logfile) + return logfile + + def _logclean(self, logfile): + t = open(logfile, "r").read().replace("\n","",1).replace("\a","") + t = t.replace('\n\n', '\n') + t = re.sub('.\[K', '', t) + while True: + tb = re.sub('.\b', '', t, count=1) + if len(t) == len(tb): + break + t = tb + d = open(logfile, "w") + d.write(t) + d.close() + return + + def connect(self, mode = None): + if self.protocol == "ssh": + cmd = "ssh" + if self.idletime > 0: + cmd = cmd + " -o ServerAliveInterval=" + str(self.idletime) + if self.user == '': + cmd = cmd + " -t {}".format(self.host) + else: + cmd = cmd + " -t {}".format("@".join([self.user,self.host])) + if self.port != '': + cmd = cmd + " -p " + self.port + if self.options != '': + cmd = cmd + " " + self.options + if self.logs != '': + logfile = self._logfile() + if self.password[0] != '': + passwords = self.__passtx(self.password) + else: + passwords = [] + expects = ['yes/no', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:|[u|U]sername:', '>$|#$|\$', 'suspend'] + elif self.protocol == "telnet": + cmd = "telnet " + self.host + if self.port != '': + cmd = cmd + " " + self.port + if self.options != '': + cmd = cmd + " " + self.options + if self.logs != '': + logfile = self._logfile() + if self.password[0] != '': + passwords = self.__passtx(self.password) + else: + passwords = [] + expects = ['[u|U]sername:', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:', '>$|#$|\$', 'suspend'] + else: + print("Invalid protocol: " + self.protocol) + return + child = pexpect.spawn(cmd) + if 'logfile' in locals(): + child.logfile_read = open(logfile, "wb") + # child.logfile_read = sys.stdout.buffer + print("Connecting to " + self.unique + " at " + self.host + (":" if self.port != '' else '') + self.port + " via: " + self.protocol) + if len(passwords) > 0: + loops = len(passwords) + else: + loops = 1 + endloop = False + for i in range(0, loops): + while True: + results = child.expect(expects) + match results: + case 0: + if self.protocol == "ssh": + child.sendline('yes') + elif self.protocol == "telnet": + if self.user != '': + child.sendline(self.user) + else: + print(child.after.decode(), end='') + break + case 1 | 2 | 3 | 4 | 5 | 6 |7: + print("Connection failed code:" + str(results)) + child.close() + return + case 8: + if len(passwords) > 0: + child.sendline(passwords[i]) + else: + print(child.after.decode(), end='') + break + case 9: + endloop = True + child.sendline() + break + case 10: + child.sendline("\r") + sleep(2) + if endloop: + break + child.readline(0) + if mode == "interact": + child.interact() + if "logfile" in locals(): + self._logclean(logfile) + +# script diff --git a/conn/tools.py b/conn/tools.py new file mode 100755 index 0000000..3b877eb --- /dev/null +++ b/conn/tools.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +#Imports +import os +from Crypto.PublicKey import RSA +from Crypto.Cipher import PKCS1_OAEP +import ast + +#Constants + +#Variables + +#functions and clsses + +def encrypt(password, keyfile=None): + if keyfile is None: + home = os.path.expanduser("~") + keyfile = home + '/.config/conn/.osk' + key = RSA.import_key(open(keyfile).read()) + publickey = key.publickey() + encryptor = PKCS1_OAEP.new(publickey) + password = encryptor.encrypt(password.encode("utf-8")) + return password + + + diff --git a/test.py b/test.py new file mode 100755 index 0000000..b0961dc --- /dev/null +++ b/test.py @@ -0,0 +1,7 @@ +#!/usr/bin/python3 +import conn + +conf = conn.configfile() +conn1=conn.node("pruebas@conn", **conf.connections["home"]["xr"]) +conn1.connect("interact") + diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..0bb98b5 --- /dev/null +++ b/test.txt @@ -0,0 +1,7 @@ +--- +config: + case: false + frun: false + idletime: 30 +connections: {} +profiles: {}