Esempio n. 1
0
 def plugin(self):
     self.sh = MockSmartHome()
     self.sh.with_items_from(common.BASE +
                             '/plugins/database/tests/test_items.conf')
     plugin = Database(self.sh, 'sqlite3', {'database': ':memory:'})
     for item in self.sh.return_items():
         plugin.parse_item(item)
     return plugin
Esempio n. 2
0
def _register_class(class_id):
    user = session.get("user").get("email")

    with Database() as db:
        class_info = db.get_class_info(class_id)
    if class_info is not None:
        with Database() as db:
            db.register_class(user, class_id)
        return "success", 201
    else:
        return "fail", 404
Esempio n. 3
0
def create_classes_db():
    with Database() as db:
        db.execute("""CREATE TABLE IF NOT EXISTS classes
            (class varchar(30) not null, name varchar(30), primary key (class))"""
                   )
        db.execute("""CREATE TABLE IF NOT EXISTS assignments
            (assignment varchar(30) not null,
            name varchar(30),
            class varchar(30) not null,
            foreign key (class) references classes(class),
            primary key (assignment, class))""")
        db.execute("""CREATE TABLE IF NOT EXISTS attempts
            (attempt INTEGER PRIMARY KEY AUTOINCREMENT,
            assignment varchar(30) not null,
            user varchar(60) not null, data text,
            score integer default 0,
            maxscore integer not null,
            foreign key (assignment) references assignments(assignment),
            foreign key (user) references users(username)
            )""")
        db.execute("""CREATE TABLE IF NOT EXISTS registry
            ( user varchar(30) not null,
            class varchar(30) not null,
            primary key (user, class),
            foreign key (user) references users(user),
            foreign key (class) references classes(class))
            """)
Esempio n. 4
0
def _assignments(class_id):
    with Database() as db:
        assignments = db.get_assignments(class_id)
        for assignment in assignments:
            attempt = db.get_latest_attempt(session.get("user").get("email"), class_id, assignment.get("assignment"))
            assignment['currScore'] = attempt.get("currScore")
            if attempt.get("testcases") is not None and len(attempt.get("testcases")) != 0:
                assignment['maxScore'] = sum([testcase.get("maxscore") for testcase in attempt.get("testcases")])
    return json.dumps(assignments)
Esempio n. 5
0
    def __init__(self):
        self.about = AboutProject()
        self.url_req = URLRequest()

        Cmd.doc_header = "Core Commands"
        Cmd.prompt = "{}belati{} > ".format(UNDERLINE, ENDC)
        Cmd.path_complete

        Cmd.__init__(self)

        self.list_parameter = ['domain', 'username', 'email', 'orgcomp', 'proxy', 'proxy_file']
        self.parameters = {}
        self.multiple_proxy_list = []
        self.current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        self.show_banner()
        self.conf = Config()
        self.db = Database()
Esempio n. 6
0
def register_user():
    if request.method == 'POST':
        with Database() as db:
            email_re = re.compile(
                r'([A-Za-z]{2,3}[0-9]{2,5}|[A-Za-z]{2,}|([A-Za-z]+\.){1,2}[A-Za-z]+)@drexel\.edu'
            )
            pass_re = re.compile(r'(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}')

            form = request.form.to_dict()
            logger.info(form)
            email = form['email'].strip()
            res = db.get_user(email)

        if res is not None:
            return render_template(
                'register.html',
                data={},
                message="User with that email already exists")
        password = form["password"].strip()
        name = form["name"].strip()
        if any([
                not pass_re.match(password), not email_re.match(email),
                len(name) == 0
        ]):
            message = ""
            if not email_re.match(email):
                message = "Email is not an @drexel.edu email"
            elif not pass_re.match(password):
                message = "Password is not secure enough"
            elif len(name) == 0:
                message = "Name was not supplied"
            return render_template('register.html', data={}, message=message)

        password = passencrypt(password)

        # create user and set session id
        with Database() as db:
            db.create_user(str(email), str(password.hex()), str(name))
        session['user'] = {"name": name, "email": email}

        return redirect('/dashboard')
    return render_template('register.html', data={}), 200
Esempio n. 7
0
def create_assignment(class_name, assignment_id, name=""):
    with Database() as db:
        try:
            db.execute("""insert into classes (class) values (?)""",
                       [class_name])
        except:
            logger.info("{} already in db", class_name)
        try:
            db.execute(
                """insert into assignments (class, assignment, name) values (?, ?, ?)""",
                [class_name, assignment_id, name])
        except:
            logger.info("{} {} already in db", class_name, assignment_id)
Esempio n. 8
0
def test_database_connection(mock_dataset, bot):
    """Tests the initialization of Database plugin.

    It creates a database connection using dataset library.

    Args:
        mock_dataset: Fakes dataset library.
        bot: Fake instance of an Irc3Bot.
    """
    con = mock.Mock()
    mock_dataset.connect.return_value = con
    Database(bot)
    assert mock_dataset.connect.called_once_with(bot.config.database)
    assert bot.dataset == con
Esempio n. 9
0
def _assignment_attempt(class_id, assn_id):
    logger.info("{} {}", class_id, assn_id)
    user = session.get("user")
    username = user.get("email")

    with Database() as db:
        attempt = db.get_latest_attempt(username, class_id, assn_id)

        if attempt.get("code", None) is not None:
            attempt = attempt.get("code")
        else:
            attempt = _class_files(class_id, assn_id, extra_file='template')

    return attempt
Esempio n. 10
0
def signin():
    if request.method == 'POST':
        form = request.form.to_dict()
        username = form.get("username")
        password = form.get("password")
        user_data = None
        with Database() as db:
            user_data = db.get_user(username)

        # failed to sign in
        if user_data is None or user_data.get('password') != passencrypt(
                password).hex():
            return render_template('signin.html',
                                   data={},
                                   message='Failed to sign in')

        # do user auth and set creds
        session['user'] = {"name": user_data.get('name'), "email": username}
        return redirect('/dashboard')
    return render_template('signin.html', data={}), 200
Esempio n. 11
0
    def __init__(self):
        self.about = AboutProject()
        self.url_req = URLRequest()

        # Passing arguments
        parser = argparse.ArgumentParser(
            description='=[ {} {} by {}] ({})'.format(
                self.about.__name__, self.about.__version__,
                self.about.__author__, self.about.__giturl__))
        parser.add_argument(
            '-d',
            action='store',
            dest='domain',
            help=
            'Perform OSINT from Domain e.g petruknisme.com(without protocol http/https)'
        )
        parser.add_argument('-u',
                            action='store',
                            dest='username',
                            help='Perform OSINT from username e.g petruknisme')
        parser.add_argument('-e',
                            action='store',
                            dest='email',
                            help='Perform OSINT from email address')
        parser.add_argument(
            '-c',
            action='store',
            dest='orgcomp',
            help=
            'Perform OSINT from Organization or Company Name, use double quote'
        )
        parser.add_argument('-o',
                            action='store',
                            dest='output_files',
                            help='Save log for output files')
        parser.add_argument('--db-file',
                            action='store',
                            dest='db_file_location',
                            help='Specify Database File Location(SQLite3)')
        parser.add_argument(
            '--single-proxy',
            action='store',
            dest='single_proxy',
            help='Proxy support with single IP (ex: http://127.0.0.1:8080)')
        parser.add_argument('--proxy-file',
                            action='store',
                            dest='proxy_file_location',
                            help='Proxy support from Proxy List File')
        parser.add_argument('--auto-proxy',
                            action='store_true',
                            dest='auto_proxy',
                            default=True,
                            help='Auto Proxy Support( Coming soon )')
        parser.add_argument('--version',
                            action='version',
                            version='=[ {} {} by {}] ({})'.format(
                                self.about.__name__, self.about.__version__,
                                self.about.__author__, self.about.__giturl__))
        results = parser.parse_args()

        domain = results.domain
        username = results.username
        email = results.email
        orgcomp = results.orgcomp
        single_proxy = results.single_proxy
        proxy_file_location = results.proxy_file_location
        proxy = ""
        self.multiple_proxy_list = []

        self.show_banner()

        conf = Config()
        self.db = Database()

        # Setup project
        self.project_id = self.db.create_new_project(domain, orgcomp,
                                                     datetime.datetime.now())
        log.console_log("{}[+] Creating New Belati Project... {}".format(G, W))
        log.console_log(
            "---------------------------------------------------------")
        log.console_log("Project ID: {}".format(str(self.project_id)))
        log.console_log("Project Domain: {}".format(domain))
        log.console_log("Project Organization/Company: {}".format(orgcomp))
        log.console_log(
            "---------------------------------------------------------")

        if domain is not None:
            if single_proxy is not None:
                log.console_log("{}[*] Checking Proxy Status... {}".format(
                    G, W))
                if self.check_single_proxy_status(single_proxy, "http://" +
                                                  str(domain)) == 'ok':
                    proxy = single_proxy
                else:
                    log.console_log(
                        '{}[-] Please use another proxy or disable proxy! {}'.
                        format(R, W))
                    sys.exit()

            if proxy_file_location is not None:
                log.console_log(
                    "{}[*] Checking Proxy Status from file {}{}".format(
                        G, proxy_file_location, W))
                self.check_multiple_proxy_status(proxy_file_location,
                                                 "http://" + str(domain))
                proxy = self.multiple_proxy_list

            extract_domain = tldextract.extract(domain)

            self.check_domain(self.url_req.ssl_checker(domain), proxy)
            self.banner_grab(self.url_req.ssl_checker(domain), proxy)

            if extract_domain.subdomain == "":
                self.robots_scraper(self.url_req.ssl_checker(domain), proxy)
                self.enumerate_subdomains(domain, proxy)
                self.scan_DNS_zone(domain)
                self.harvest_email_search(domain, proxy)
                self.harvest_email_pgp(domain, proxy)
            else:
                domain = extract_domain.domain + '.' + extract_domain.suffix
                self.robots_scraper(self.url_req.ssl_checker(domain), proxy)
                self.enumerate_subdomains(domain, proxy)
                self.scan_DNS_zone(domain)
                self.harvest_email_search(domain, proxy)
                self.harvest_email_pgp(domain, proxy)

            self.harvest_document(domain, proxy)

        if username is not None:
            self.username_checker(username)

        if orgcomp is not None:
            self.gather_company(orgcomp, proxy)

        if email is not None:
            log.console_log("This feature will be coming soon. Be patient :)")

        log.console_log(
            "{}All done sir! All log saved in log directory and dowloaded file saved in belatiFiles {}"
            .format(Y, W))
Esempio n. 12
0
class Belati(object):
    def __init__(self):
        self.about = AboutProject()
        self.url_req = URLRequest()

        # Passing arguments
        parser = argparse.ArgumentParser(
            description='=[ {} {} by {}] ({})'.format(
                self.about.__name__, self.about.__version__,
                self.about.__author__, self.about.__giturl__))
        parser.add_argument(
            '-d',
            action='store',
            dest='domain',
            help=
            'Perform OSINT from Domain e.g petruknisme.com(without protocol http/https)'
        )
        parser.add_argument('-u',
                            action='store',
                            dest='username',
                            help='Perform OSINT from username e.g petruknisme')
        parser.add_argument('-e',
                            action='store',
                            dest='email',
                            help='Perform OSINT from email address')
        parser.add_argument(
            '-c',
            action='store',
            dest='orgcomp',
            help=
            'Perform OSINT from Organization or Company Name, use double quote'
        )
        parser.add_argument('-o',
                            action='store',
                            dest='output_files',
                            help='Save log for output files')
        parser.add_argument('--db-file',
                            action='store',
                            dest='db_file_location',
                            help='Specify Database File Location(SQLite3)')
        parser.add_argument(
            '--single-proxy',
            action='store',
            dest='single_proxy',
            help='Proxy support with single IP (ex: http://127.0.0.1:8080)')
        parser.add_argument('--proxy-file',
                            action='store',
                            dest='proxy_file_location',
                            help='Proxy support from Proxy List File')
        parser.add_argument('--auto-proxy',
                            action='store_true',
                            dest='auto_proxy',
                            default=True,
                            help='Auto Proxy Support( Coming soon )')
        parser.add_argument('--version',
                            action='version',
                            version='=[ {} {} by {}] ({})'.format(
                                self.about.__name__, self.about.__version__,
                                self.about.__author__, self.about.__giturl__))
        results = parser.parse_args()

        domain = results.domain
        username = results.username
        email = results.email
        orgcomp = results.orgcomp
        single_proxy = results.single_proxy
        proxy_file_location = results.proxy_file_location
        proxy = ""
        self.multiple_proxy_list = []

        self.show_banner()

        conf = Config()
        self.db = Database()

        # Setup project
        self.project_id = self.db.create_new_project(domain, orgcomp,
                                                     datetime.datetime.now())
        log.console_log("{}[+] Creating New Belati Project... {}".format(G, W))
        log.console_log(
            "---------------------------------------------------------")
        log.console_log("Project ID: {}".format(str(self.project_id)))
        log.console_log("Project Domain: {}".format(domain))
        log.console_log("Project Organization/Company: {}".format(orgcomp))
        log.console_log(
            "---------------------------------------------------------")

        if domain is not None:
            if single_proxy is not None:
                log.console_log("{}[*] Checking Proxy Status... {}".format(
                    G, W))
                if self.check_single_proxy_status(single_proxy, "http://" +
                                                  str(domain)) == 'ok':
                    proxy = single_proxy
                else:
                    log.console_log(
                        '{}[-] Please use another proxy or disable proxy! {}'.
                        format(R, W))
                    sys.exit()

            if proxy_file_location is not None:
                log.console_log(
                    "{}[*] Checking Proxy Status from file {}{}".format(
                        G, proxy_file_location, W))
                self.check_multiple_proxy_status(proxy_file_location,
                                                 "http://" + str(domain))
                proxy = self.multiple_proxy_list

            extract_domain = tldextract.extract(domain)

            self.check_domain(self.url_req.ssl_checker(domain), proxy)
            self.banner_grab(self.url_req.ssl_checker(domain), proxy)

            if extract_domain.subdomain == "":
                self.robots_scraper(self.url_req.ssl_checker(domain), proxy)
                self.enumerate_subdomains(domain, proxy)
                self.scan_DNS_zone(domain)
                self.harvest_email_search(domain, proxy)
                self.harvest_email_pgp(domain, proxy)
            else:
                domain = extract_domain.domain + '.' + extract_domain.suffix
                self.robots_scraper(self.url_req.ssl_checker(domain), proxy)
                self.enumerate_subdomains(domain, proxy)
                self.scan_DNS_zone(domain)
                self.harvest_email_search(domain, proxy)
                self.harvest_email_pgp(domain, proxy)

            self.harvest_document(domain, proxy)

        if username is not None:
            self.username_checker(username)

        if orgcomp is not None:
            self.gather_company(orgcomp, proxy)

        if email is not None:
            log.console_log("This feature will be coming soon. Be patient :)")

        log.console_log(
            "{}All done sir! All log saved in log directory and dowloaded file saved in belatiFiles {}"
            .format(Y, W))

    def show_banner(self):
        banner = """
        {}
         /$$$$$$$  /$$$$$$$$ /$$        /$$$$$$  /$$$$$$$$ /$$$$$$
        | $$__  $$| $$_____/| $$       /$$__  $$|__  $$__/|_  $$_/
        | $$  \ $$| $$      | $$      | $$  \ $$   | $$     | $$
        | $$$$$$$ | $$$$$   | $$      | $$$$$$$$   | $$     | $$
        | $$__  $$| $$__/   | $$      | $$__  $$   | $$     | $$
        | $$  \ $$| $$      | $$      | $$  | $$   | $$     | $$
        | $$$$$$$/| $$$$$$$$| $$$$$$$$| $$  | $$   | $$    /$$$$$$
        |_______/ |________/|________/|__/  |__/   |__/   |______/

                                The Traditional Swiss Army Knife for OSINT

        =[ {} {} by {}]=

        + -- --=[ {} ]=-- -- +
        + -- --=[ {} ]=-- -- +
        {}
        """

        warning_message = """
        {}
        This tool is for educational purposes only.
        Any damage you make will not affect the author.
        Do It With Your Own Risk!

        For Better Privacy, Please Use proxychains or other proxy service!
        {}
        """

        log.console_log(
            banner.format(G, self.about.__name__, self.about.__version__,
                          self.about.__author__, self.about.__info__,
                          self.about.__authorurl__, W))
        log.console_log(warning_message.format(R, W))

    def check_domain(self, domain_name, proxy_address):
        check = CheckDomain()

        log.console_log(
            G + "{}[*] Checking Domain Availability... {}".format(G, W), 0)
        check.domain_checker(domain_name, proxy_address)
        log.console_log("{}[*] Checking URL Alive... {}".format(G, W), 0)
        check.alive_check(domain_name, proxy_address)
        log.console_log("{}[*] Perfoming Whois... {}".format(G, W))
        whois_result = check.whois_domain(domain_name)
        email = re.findall(r'[a-zA-Z0-9._+-]+@[a-zA-Z0-9._+-]+\s*',
                           str(whois_result))
        self.db.insert_domain_result(self.project_id,
                                     self.strip_scheme(domain_name),
                                     str(whois_result), str(email))

    def banner_grab(self, domain_name, proxy_address):
        banner = BannerGrab()
        log.console_log("{}[*] Perfoming HTTP Banner Grabbing... {}".format(
            G, W))
        banner_info = banner.show_banner(domain_name, proxy_address)
        self.db.insert_banner(domain_name, self.project_id, str(banner_info))

    def enumerate_subdomains(self, domain_name, proxy):
        log.console_log("{}[*] Perfoming Subdomains Enumeration... {}".format(
            G, W))
        subdomain_list = sublist3r.main(domain_name,
                                        100,
                                        "",
                                        ports=None,
                                        silent=False,
                                        verbose=False,
                                        enable_bruteforce=False,
                                        engines=None)
        subdomain_ip_list = []

        for subdomain in subdomain_list:
            self.banner_grab(self.url_req.ssl_checker(subdomain), proxy)
            self.robots_scraper(self.url_req.ssl_checker(subdomain), proxy)
            self.wappalyzing_webpage(subdomain)
            self.public_git_finder(subdomain, proxy)
            self.public_svn_finder(subdomain, proxy)
            try:
                subdomain_ip_list.append(socket.gethostbyname(subdomain))
                self.db.update_subdomain_ip(
                    self.project_id, subdomain,
                    str(socket.gethostbyname(subdomain)))
            except socket.gaierror:
                pass

        subdomain_ip_listFix = list(set(subdomain_ip_list))

        # check common service port TODO
        #for ipaddress in subdomain_ip_listFix:
        #self.common_service_check(ipaddress)

        for ipaddress in subdomain_ip_listFix:
            self.service_scanning(ipaddress)

    def wappalyzing_webpage(self, domain):
        log.console_log("{}[*] Wapplyzing on domain {}{}".format(G, domain, W))
        wappalyzing = Wappalyzer()
        targeturl = self.url_req.ssl_checker(domain)
        try:
            data = wappalyzing.run_wappalyze(targeturl)
            self.db.insert_wappalyzing(self.project_id, domain, data)
        except urllib2.URLError as exc:
            log.console_log('URL Error: {0}'.format(str(exc)))
        except urllib2.HTTPError as exc:
            log.console_log('HTTP Error: {0}'.format(str(exc)))
        except Exception as exc:
            log.console_log('Unknow error: {0}'.format(str(exc)))

    def service_scanning(self, ipaddress):
        scan_nm = ScanNmap()
        log.console_log("{}[*] Perfoming Nmap Full Scan on IP {}{}".format(
            G, ipaddress, W))
        log.console_log("{}[*] nmap -sS -A -Pn {}{}".format(G, ipaddress, W))
        scan_nm.run_scanning(ipaddress)

    def scan_DNS_zone(self, domain_name):
        log.console_log("{}[*] Perfoming DNS Zone Scanning... {}".format(G, W))
        log.console_log(
            "{}[*] Please wait, maximum timeout for checking is 1 minutes {}".
            format(G, W))
        signal.signal(signal.SIGALRM, self.timeLimitHandler)
        signal.alarm(60)
        try:
            scan_list = str(list(Scanner(domain_name).scan()))
            ns_record_list = []
            mx_record_list = []
            log.console_log("{}{}{}".format(G, scan_list.replace(",", "\n"),
                                            W))
            log.console_log("{}DNS Server:{}".format(G, W))
            for ns in dns.resolver.query(domain_name, 'NS'):
                log.console_log(G + ns.to_text() + W)
                ns_record_list.append(ns.to_text())

            log.console_log("{}MX Record:{}".format(G, W))
            for ns in dns.resolver.query(domain_name, 'MX'):
                log.console_log("{}{}{}".format(G, ns.to_text(), W))
                mx_record_list.append(ns.to_text())

            self.db.update_dns_zone(self.project_id, domain_name,
                                    str(ns_record_list), str(mx_record_list))

        except Exception, exc:
            print("{}[*] No response from server... SKIP!{}".format(R, W))
Esempio n. 13
0
def _registered_class():
    user = session.get("user").get("email")
    with Database() as db:
        classes = db.get_registered_classes(user)
    return json.dumps(classes)
Esempio n. 14
0
def _classes():
    user = session.get("user").get("email")
    with Database() as db:
        assignments = db.get_classes_not_registered(user)
    return json.dumps(assignments)
Esempio n. 15
0
def _class_assignment(class_name, assn_num):
    path = f'{class_name}/{assn_num}'
    if path not in available_tests:
        return abort(404)
    if request.method == 'POST':
        body = request.get_json(force=True)
        harness_method = body.get('method')
        if harness_method not in ['test', 'submit']:
            return json.dumps({'status': 'error',
                               'output': ['Invalid harness method']}), 401

        dotenv.load_dotenv(os.path.abspath(f'{TEST_DIR}/{path}/config'))

        with open(os.path.abspath(f'{TEST_DIR}/{path}/{os.getenv("FILE_NAME")}'), 'w') as f:
            f.write(body.get('code'))

        test_case_outputs = []
        score = 0
        maxscore = 0
        if harness_method == 'submit':
            with open(os.path.abspath(f'{TEST_DIR}/{path}/testcases.json'), 'r') as f:
                for testcase in json.load(f):
                    logger.info("Running {}", testcase.get('file'))
                    ret, output, error = run_subprocess(
                        ['python3', '-m', 'unittest', '-v', testcase.get('file')], f'{TEST_DIR}/{path}')
                    test_case_outputs.append(
                        {
                            "id": testcase.get('file'),
                            "file": testcase.get('file'),
                            "name": testcase.get("name"),
                            "score": testcase.get('maxscore') if ret == 0 else 0,
                            "maxscore": testcase.get('maxscore')
                        }
                    )
                    logger.info("Output: {}", ret)
                    score += testcase.get('maxscore') if ret == 0 else 0
                    maxscore += testcase.get('maxscore')

                data = {
                    "testcases": test_case_outputs,
                    "currScore": score,
                    "code": body.get("code")
                }
                with Database() as db:
                    db.set_latest_attempt(
                        session.get("user").get("email"),
                        assn_num,
                        json.dumps(data),
                        score=score,
                        maxscore=maxscore
                    )
        else:
            ret, output, error = run_subprocess(
                ['bash', './run.sh', harness_method], f'{TEST_DIR}/{path}')

        return _create_return_json(ret, output, error, harness_method, score=score, data=test_case_outputs), 201

    # GET
    test_cases = get_test_cases(class_name, assn_num)
    curr_score = 0
    with Database() as db:
        name = db.get_class_info(class_name).get("name")
        prev_attempt = db.get_latest_attempt(
            session.get("user").get("email"), class_name, assn_num)
        if prev_attempt:
            curr_score = prev_attempt.get("currScore")
            test_cases = prev_attempt.get("testcases")

    data = {
        "assignment": assn_num,
        "name": name,
        "currScore": curr_score,
        "user": session.get("user"),
        "testcases": test_cases,
        "maxScore": sum([tc.get('maxscore') for tc in test_cases])
    }
    return render_template('editor.html', data=data)
Esempio n. 16
0
class Belati(Cmd):
    def __init__(self):
        self.about = AboutProject()
        self.url_req = URLRequest()

        Cmd.doc_header = "Core Commands"
        Cmd.prompt = "{}belati{} > ".format(UNDERLINE, ENDC)
        Cmd.path_complete

        Cmd.__init__(self)

        self.list_parameter = ['domain', 'username', 'email', 'orgcomp', 'proxy', 'proxy_file']
        self.parameters = {}
        self.multiple_proxy_list = []
        self.current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        self.show_banner()
        self.conf = Config()
        self.db = Database()


    def show_banner(self):
        banner = """
        {}

         /$$$$$$$  /$$$$$$$$ /$$        /$$$$$$  /$$$$$$$$     .
        | $$__  $$| $$_____/| $$       /$$__  $$|__  $$__/    J:L
        | $$  \ $$| $$      | $$      | $$  \ $$   | $$       |:|
        | $$$$$$$ | $$$$$   | $$      | $$$$$$$$   | $$       |:|
        | $$__  $$| $$__/   | $$      | $$__  $$   | $$       |:|
        | $$  \ $$| $$      | $$      | $$  | $$   | $$       |:|
        | $$$$$$$/| $$$$$$$$| $$$$$$$$| $$  | $$   | $$   /]  |:|  [\ 
        |_______/ |________/|________/|__/  |__/   |__/   \:-'\"""'-:/
                                                            ""III""
                                                              III
                                                              III
                                                              III
                                                             (___)

                                The Traditional Swiss Army Knife for OSINT

        =[ {} {} by {}]=

        + -- --=[ {} ]=-- -- +
        + -- --=[ {} ]=-- -- +
        {}
        """

        warning_message = """
        {}
        This tool is for educational purposes only.
        Any damage you make will not affect the author.
        Do It With Your Own Risk!

        For Better Privacy, Please Use proxychains or other proxy service!
        {}
        """

        log.console_log(banner.format(G, self.about.__name__, self.about.__version__, self.about.__author__, self.about.__info__, self.about.__authorurl__, W))
        log.console_log(warning_message.format(R, W))

    def do_help(self, line):
    	'print help message'

    	print("\nCore commands")
    	print("==============\n")
    	print tabulate([["Name","Description"],
    		["?", "Help menu"],
    		["!", "Run OS Command"],
    		["history", "Show command history"],
    		["set", "Set parameters option value"],
    		["show", "Display list available parameter option"],
    		["start", "Start Automatic Scanning Belati"],
    		["startws", "Start Web Server Only Mode"],
    		["version", "Show application version number"],
    		["quit", "Exit the application"]],
			headers="firstrow")


    def do_set(self, arg, opts=None):
    	'''Set Variable for Belati parameters.\nUsage: set [option] [value]\n\nAvailable options:\ndomain, username, email, orgcomp, proxy, proxy_file'''

    	if not arg:
    		log.console_log('{} Set Variable for Belati parameters.\nUsage: set [option] [value]\n\nAvailable options:\ndomain, username, email, orgcomp, proxy, proxy_file {}'.format(W, W))
    	else:
            param = shlex.split(arg)
            key = param[0]
            value = param[1]
            if key in self.list_parameter:
                self.parameters[key] = value
                log.console_log('{} => {}'.format(self.parameters[key], value))
            else:
                log.console_log("Available parameters: domain, username, email, orgcomp, proxy, proxy_file")

    def do_show(self, arg, opts=None):
    	'Show available parameter options'
    	
    	domain_val = self.parameters['domain'] if 'domain' in self.parameters else None
    	orgcomp = self.parameters['orgcomp'] if 'orgcomp' in self.parameters else None
     	email = self.parameters['email'] if 'email' in self.parameters else None
     	username = self.parameters['username'] if 'username' in self.parameters else None
     	proxy = self.parameters['proxy'] if 'proxy' in self.parameters else None
     	proxy_file = self.parameters['proxy_file'] if 'proxy_file' in self.parameters else None
     	org_val = ""
    	arg = shlex.split(arg)

    	if not arg:
    		print("Please use command 'show options' to see list of option parameters")

    	elif arg[0] == "options":
            print tabulate([["Name","Value", "Required", "Description"],
    			["domain", domain_val, "Yes", "Domain name for OSINT"],
    			["orgcomp", orgcomp, "Yes", "Organization/Company name for OSINT"],
    			["email", email, "Optional", "Email address for OSINT"],
    			["username", username, "Optional", "Username for OSINT"],
    			["proxy", proxy, "Optional", "Proxy server(e.g http://127.0.0.1:8080)"],
    			["proxy_file", proxy_file, "Optional", "Proxy file list location"]],
    			headers="firstrow")

    def do_startws(self, line):
    	'Start Belati in Web Server Only Mode'
    	
    	log.console_log("{}[*] Entering Web Server Only Mode...{}".format(Y,W))
    	self.start_web_server()
    	sys.exit()

    def do_version(self, line):
    	'Check current Belati version'
    	
    	log.console_log('{} {} by {}\n'.format(self.about.__name__, self.about.__version__, self.about.__author__))
    	log.console_log('Project URL: {}'.format(self.about.__giturl__))

    def do_start(self, line):
    	'Start automatic scanning'
    	domain = self.parameters['domain'] if 'domain' in self.parameters else None
    	orgcomp = self.parameters['orgcomp'] if 'orgcomp' in self.parameters else None
     	email = self.parameters['email'] if 'email' in self.parameters else None
     	username = self.parameters['username'] if 'username' in self.parameters else None
     	proxy = self.parameters['proxy'] if 'proxy' in self.parameters else ''
     	proxy_file = self.parameters['proxy_file'] if 'proxy_file' in self.parameters else ''

    	if domain is None and orgcomp is None:
    		log.console_log("{}[-] Please specify domain/organization {}".format(R,W))
    		sys.exit()
			
		log.console_log("{}[*] Starting at: {} {}".format(Y, self.current_time , W))

        self.updater = Updater()
        self.updater.check_update(self.about.__version__)

        # Setup project
        self.project_id = self.db.create_new_project(domain, orgcomp, self.current_time)
        log.console_log("{}[+] Creating New Belati Project... {}".format(G, W))
        log.console_log("---------------------------------------------------------")
        log.console_log("Project ID: {}".format(str(self.project_id)))
        log.console_log("Project Domain: {}".format(domain))
        log.console_log("Project Organization/Company: {}".format(orgcomp))
        log.console_log("---------------------------------------------------------")

        if domain is not None:
            if proxy is not '':
                log.console_log("{}[*] Checking Proxy Status... {}".format(G, W))
                if self.check_single_proxy_status(proxy, "http://" + str(domain)) == 'ok':
                    pass
                else:
                    log.console_log('{}[-] Please use another proxy or disable proxy! {}'.format(R, W))
                    sys.exit()

            if proxy_file is not '':
                log.console_log("{}[*] Checking Proxy Status from file {}{}".format(G, proxy_file, W))
                self.check_multiple_proxy_status(proxy_file, "http://" + str(domain))
                proxy = self.multiple_proxy_list

            extract_domain = tldextract.extract(domain)

            self.check_domain(self.url_req.ssl_checker(domain), proxy)
            self.banner_grab(self.url_req.ssl_checker(domain), proxy)

            if extract_domain.subdomain == "":
                self.robots_scraper(self.url_req.ssl_checker(domain), proxy)
                self.enumerate_subdomains(domain, proxy)
                self.scan_DNS_zone(domain)
                self.harvest_email_search(domain, proxy)
                self.harvest_email_pgp(domain, proxy)
            else:
                domain = extract_domain.domain + '.' + extract_domain.suffix
                self.robots_scraper(self.url_req.ssl_checker(domain), proxy)
                self.enumerate_subdomains(domain, proxy)
                self.scan_DNS_zone(domain)
                self.harvest_email_search(domain, proxy)
                self.harvest_email_pgp(domain, proxy)

            self.harvest_document(domain, proxy)

        if username is not None:
            self.username_checker(username)

        if orgcomp is not None:
            self.gather_company(orgcomp, proxy)

        if email is not None:
            log.console_log("This feature will be coming soon. Be patient :)")

        log.console_log("{}All done sir! All logs saved in {}logs{} directory and dowloaded file saved in {}belatiFiles{} {}".format(Y, B, Y, B, Y, W))

        self.start_web_server()

    def check_domain(self, domain_name, proxy_address):
        check = CheckDomain()

        log.console_log(G + "{}[*] Checking Domain Availability... {}".format(G, W) , 0)
        log.console_log(check.domain_checker(domain_name, proxy_address))
        
        log.console_log("{}[*] Checking URL Alive... {}".format(G, W), 0)
        log.console_log(check.alive_check(domain_name, proxy_address))

        log.console_log("{}[*] Perfoming Whois... {}".format(G, W))
        whois_result = check.whois_domain(domain_name)
        log.console_log(whois_result)
        email = re.findall(r'[a-zA-Z0-9._+-]+@[a-zA-Z0-9._+-]+\s*', str(whois_result))

        # JSON Beautifier
        json_bf = JsonBeautifier()
        json_whois = json_bf.beautifier(str(whois_result))
        self.db.insert_domain_result(self.project_id, util.strip_scheme(domain_name), str(json_whois), util.clean_list_string(email))

    def banner_grab(self, domain_name, proxy_address):
        banner = BannerGrab()
        log.console_log("{}[*] Perfoming HTTP Banner Grabbing... {}".format(G, W))
        banner_info = banner.show_banner(domain_name, proxy_address)
        log.console_log(banner_info)
        self.db.insert_banner(domain_name, self.project_id, str(banner_info))

    def enumerate_subdomains(self, domain_name, proxy):
        log.console_log("{}[*] Perfoming Subdomains Enumeration...{}".format(G, W))
        sub_enum = SubdomainEnum()
        log.console_log("{}[+] Grabbing data from dnsdumpster...{}\n".format(B, W))
        dnsdumpster = sub_enum.scan_dnsdumpster(domain_name)
        subdomain_list = []
        data_table = [["Domain", "IP", "Provider", "Country"]]
        for entry in dnsdumpster['dns_records']['host']:
            data_table.extend([[entry['domain'], entry['ip'], entry['provider'], entry['country']]])
            subdomain_list.append(entry['domain'])

        log.console_log( tabulate(data_table, headers='firstrow') )

        log.console_log("{}[+] Grabbing data from crt.sh...{}\n".format(B, W))
        crt_list = sub_enum.scan_crtsh(domain_name, proxy)
        
        if crt_list is not None:
            log.console_log("\n".join(crt_list))
            subdomain_list = list(set(subdomain_list + crt_list))
        
        log.console_log("{}[+] Grabbing data from findsubdomains.com...{}\n".format(B, W))
        findsubdomains_list = sub_enum.scan_findsubdomainsCom(domain_name,proxy)
        
        if findsubdomains_list is not None:
            log.console_log("\n".join(findsubdomains_list))
            subdomain_list = list(set(subdomain_list + findsubdomains_list))

        subdomain_ip_list = []

        for subdomain in subdomain_list:
            self.banner_grab(self.url_req.ssl_checker(subdomain), proxy)
            self.robots_scraper(self.url_req.ssl_checker(subdomain), proxy)
            self.wappalyzing_webpage(subdomain)
            self.public_git_finder(subdomain, proxy)
            self.public_svn_finder(subdomain, proxy)
            try:
                subdomain_ip_list.append(socket.gethostbyname(subdomain))
                self.db.update_subdomain_ip(self.project_id, subdomain, str(socket.gethostbyname(subdomain)))
            except socket.gaierror:
                pass

        subdomain_ip_listFix = list(set(subdomain_ip_list))

        # check common service port TODO
        #for ipaddress in subdomain_ip_listFix:
            #self.common_service_check(ipaddress)

        for ipaddress in subdomain_ip_listFix:
            self.service_scanning(ipaddress)

    def wappalyzing_webpage(self, domain):
        log.console_log("{}[*] Wapplyzing on domain {}{}".format(G, domain, W))
        wappalyzing = Wappalyzer()
        targeturl = self.url_req.ssl_checker(domain)
        try:
            data = wappalyzing.run_wappalyze(targeturl)
            self.db.insert_wappalyzing(self.project_id, domain, data)
        except urllib2.URLError as exc:
            log.console_log('URL Error: {0}'.format(str(exc)))
        except urllib2.HTTPError as exc:
            log.console_log('HTTP Error: {0}'.format(str(exc)))
        except Exception as exc:
            log.console_log('Unknown error: {0}'.format(str(exc)))

    def service_scanning(self, ipaddress):
        scan_nm = ScanNmap()
        log.console_log("{}[*] Perfoming Nmap Full Scan on IP {}{}".format(G, ipaddress, W))
        log.console_log("{}[*] nmap -sS -A -Pn {}{}".format(G, ipaddress, W))
        scan_nm.run_scanning(ipaddress)

    def scan_DNS_zone(self, domain_name):
        log.console_log("{}[*] Perfoming DNS Zone Scanning... {}".format(G, W))
        log.console_log("{}[*] Please wait, maximum timeout for checking is 1 minutes {}".format(G, W))
        signal.signal(signal.SIGALRM, self.timeLimitHandler)
        signal.alarm(60)
        try:
            scan_list = str(list(Scanner(domain_name).scan()))
            ns_record_list = []
            mx_record_list = []
            log.console_log("{}{}{}".format(G, scan_list.replace(",","\n"), W))
            log.console_log("{}DNS Server:{}".format(G, W))
            for ns in dns.resolver.query(domain_name, 'NS'):
                log.console_log(G + ns.to_text() + W)
                ns_record_list.append(ns.to_text())

            log.console_log("{}MX Record:{}".format(G, W))
            for ns in dns.resolver.query(domain_name, 'MX'):
                log.console_log("{}{}{}".format(G, ns.to_text(), W))
                mx_record_list.append(ns.to_text())

            self.db.update_dns_zone(self.project_id, domain_name, util.clean_list_string(ns_record_list), util.clean_list_string(mx_record_list))

        except Exception, exc:
            print("{}[*] No response from server... SKIP!{}".format(R, W))