#!/usr/bin/python2
#
# Released with GNU GENERAL PUBLIC LICENSE, http://www.gnu.org/licenses/gpl.html
#
# Tool is written by Oskar Stridsman ostridsman@bredband.net
#
# Visit Oskar Stridsman's IT Resource - stridsmanIT.wordpress.com
#
# Released as version 0.1.1 December 01, 2012


import time
import sys
import os
import getopt
import thread
import wx
import socket
import paramiko


ID_NEW = 1
ID_RENAME = 2
ID_CLEAR = 3
ID_DELETE = 4
ID_USR = 5
ID_PSW = 6
ID_SCN = 7

SCAN_INDEX = 1


class HostBox(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(946, 686))

        panel = wx.Panel(self, -1)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.scanindex = 1
        self.usernames = "admin;root;guest"
        self.passwords = "blank;password;-username"

        self.listbox = wx.ListBox(panel, -1)
        hbox.Add(self.listbox, 1, wx.EXPAND | wx.ALL, 20)

        vbox = wx.BoxSizer(wx.VERTICAL)
        btnPanel = wx.Panel(panel, -1)
        new = wx.Button(btnPanel, ID_NEW, 'Import', size=(90, 30))
        ren = wx.Button(btnPanel, ID_RENAME, 'Rename', size=(90, 30))
        dlt = wx.Button(btnPanel, ID_DELETE, 'Delete', size=(90, 30))
        clr = wx.Button(btnPanel, ID_CLEAR, 'Clear', size=(90, 30))
        setusr = wx.Button(btnPanel, ID_USR, 'Set Usernames', size=(120, 30))
        setpass = wx.Button(btnPanel, ID_PSW, 'Set Passwords', size=(120, 30))
        startscan = wx.Button(btnPanel, ID_SCN, 'Start Scan', size=(120, 30))
        self.skipacc = wx.CheckBox(btnPanel,-1, 'skip on successful account login')
        self.skipsrv = wx.CheckBox(btnPanel,-1, 'skip on successful server login')

        self.Bind(wx.EVT_BUTTON, self.NewItem, id=ID_NEW)
        self.Bind(wx.EVT_BUTTON, self.OnRename, id=ID_RENAME)
        self.Bind(wx.EVT_BUTTON, self.OnDelete, id=ID_DELETE)
        self.Bind(wx.EVT_BUTTON, self.OnClear, id=ID_CLEAR)
        self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnRename)
        self.Bind(wx.EVT_BUTTON, self.Usr, id=ID_USR)
        self.Bind(wx.EVT_BUTTON, self.Psw, id=ID_PSW)
        self.Bind(wx.EVT_BUTTON, self.Scan, id=ID_SCN)

        vbox.Add((-1, 20))
        vbox.Add(new)
        vbox.Add(ren, 0, wx.TOP, 5)
        vbox.Add(dlt, 0, wx.TOP, 5)
        vbox.Add(clr, 0, wx.TOP, 5)
        vbox.Add(setusr, 0, wx.TOP, 5)
        vbox.Add(setpass, 0, wx.TOP, 5)
        vbox.Add((-1, 55))
        vbox.Add(startscan, 0, wx.TOP, 5)
        vbox.Add((-1, 55))
        vbox.Add(self.skipacc, 0, wx.TOP, 5)
        vbox.Add(self.skipsrv, 0, wx.TOP, 5)

        btnPanel.SetSizer(vbox)
        hbox.Add(btnPanel, 0.6, wx.EXPAND | wx.RIGHT, 20)
        panel.SetSizer(hbox)

        self.Centre()
        self.Show(True)


    def funcScan(self,hosts,index,skipacc,skipsrv):

        breakacc = False
        breaksrv = False
        users = []
        passw = []
        if ';' in self.usernames:
            users = self.usernames.split(';')
        elif ',' in self.usernames:
            users = self.usernames.split(',')
        else:
            users.append(self.usernames)

        if ";" in self.passwords:
            passw = self.passwords.split(';')
        elif "," in self.passwords:
            passw = self.passwords.split(',')
        else:
            passw.append(self.passwords)

        pathname = ""
        localtime = time.asctime( time.localtime(time.time()) )
        localtime = localtime.replace(' ', '_')
        ext = ["logs/",localtime, ".slg"]
        pathname = pathname.join(ext)
        flogfile = open(pathname, "w")

        for h in hosts:
            s = socket.socket()
            try:
                s.connect((h, 22))
                s.close()

                for u in users:
                    if breaksrv:
                        breaksrv = False
                        break
                    if breakacc:
                        breakacc = False
                        next


                    for p in passw:

                        if breakacc:
                            breakacc = False
                            break
                        if breaksrv:
                            break

                        if p == 'blank':
                            p = ''
                        if p == '-username':
                            p = u

                        ssh = paramiko.SSHClient()
                        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                        print "%s: Logging in with %s / %s" % (h,u,p)

                        try:
                            msg = ssh.connect(h, username=u, password=p)

                            if msg == None:
                                print("On Host: %s found login combination: %s / %s" % (h,u,p))
                                flogfile.write("On Host: %s found login combination: %s / %s\n" % (h,u,p))
                                ssh.close()
                                if skipacc:
                                    breakacc = True
                                if skipsrv:
                                    breaksrv = True

                        except:
                            pass

                    if breaksrv:
                        breaksrv = False
                        break
            except Exception, e:
                print "%s: Host Unreachable. Skipping to next!" % (h)
                next

        print "Scan %i has finished." % (index)
        flogfile.close()

    def Scan(self, event):
        global SCAN_INDEX
        index = SCAN_INDEX
        hosts = self.listbox.GetStrings()
        skipacc = False
        skipsrv = False

        if self.skipacc.GetValue():
            skipacc = True

        if self.skipsrv.GetValue():
            skipsrv = True

        thread.start_new_thread(self.funcScan,(hosts,index,skipacc,skipsrv))



        SCAN_INDEX += 1
        wx.MessageBox('Scanner started, positive results will be written to the log directory', 'Info', wx.OK | wx.ICON_INFORMATION)



    def Usr(self, event):
        sel = self.usernames
        text = sel
        renamed = wx.GetTextFromUser('Rename item', 'Set usernames', text)
        if renamed != '':
            self.usernames = renamed


    def Psw(self, event):
        sel = self.passwords
        text = sel
        renamed = wx.GetTextFromUser('Rename item', 'Set passwords', text)
        if renamed != '':
            self.passwords = renamed

    def NewItem(self, event):
        filters = 'All files (*.*)|*.*|Stridsman Logfiles (*.slg)|*.slg'

        dialog = wxFileDialog ( None, message = 'Open something....', wildcard = filters, style = wxOPEN | wxMULTIPLE )

        if dialog.ShowModal() == wxID_OK:


            selected = dialog.GetPath()

            dialog.Destroy()
            fobject = open(selected, "r")
            hostlines = fobject.readlines()
            fobject.close()

            if "# Nmap" in hostlines[0]:
                succimport = False
                for l in hostlines:
                    if "Ports: 22/open/" in l:
                       ip = l.split(' ')
                       self.listbox.Append(ip[1])
                       succimport = True
                if succimport == False:
                    wx.MessageBox('No open ssh ports found in the selected file (or not a greppable nmap log!)', 'Info', wx.OK | wx.ICON_INFORMATION)



            else:
                for lines in hostlines:
                    lines = lines.strip('\n')
                    self.listbox.Append(lines)

    def OnRename(self, event):
        sel = self.listbox.GetSelection()
        text = self.listbox.GetString(sel)
        renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
        if renamed != '':
            self.listbox.Delete(sel)
            self.listbox.Insert(renamed, sel)


    def OnDelete(self, event):
        sel = self.listbox.GetSelection()
        if sel != -1:
            self.listbox.Delete(sel)

    def OnClear(self, event):
        self.listbox.Clear()


def printHelp():
    os.system("clear")
    print 'HostBox-SSH.py -i <ip list> -u user1,user2,user3.. -p pass1,pass2,pass3.. [-1/-2]'
    print '\nBreak Option: -1: Break on account login'
    print '\n              -2: Break on server login\n\n'

def consoleScan(hostlist,usernames,passwords,skipacc,skipsrv):

    breakacc = False
    breaksrv = False
    users = []
    passw = []

    if ';' in usernames:
        users = usernames.split(';')
    elif ',' in usernames:
        users = usernames.split(',')
    else:
        users.append(usernames)
    if ";" in passwords:
        passw = passwords.split(';')
    elif "," in passwords:
        passw = passwords.split(',')
    else:
        passw.append(passwords)


    pathname = ""
    localtime = time.asctime( time.localtime(time.time()) )
    localtime = localtime.replace(' ', '_')
    ext = ["logs/",localtime, ".slg"]
    pathname = pathname.join(ext)
    flogfile = open(pathname, "w")
    os.system("clear")

    for h in hostlist:
        s = socket.socket()
        try:
            s.connect((h, 22))
            s.close()

            for u in users:

                if breakacc:
                    breakacc = False
                    next


                for p in passw:

                    if breakacc:
                        breakacc = False
                        break
                    if breaksrv:
                        break

                    if p == 'blank':
                        p = ''
                    if p == '-username':
                        p = u

                    ssh = paramiko.SSHClient()
                    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                    print "%s: Logging in with %s / %s" % (h,u,p)

                    try:
                        msg = ssh.connect(h, username=u, password=p)

                        if msg == None:
                            print("On Host: %s found login combination: %s / %s" % (h,u,p))
                            flogfile.write("On Host: %s found login combination: %s / %s\n" % (h,u,p))
                            ssh.close()
                            if skipacc:
                                breakacc = True
                            if skipsrv:
                                breaksrv = True




                    except:
                        pass
                if breaksrv:
                    breaksrv = False
                    break
        except Exception, e:
            print "%s: Host Unreachable. Skipping to next!" % (h)
            next

    print "Scan %s has finished." % (localtime)
    flogfile.close()


def main(argv):

    app = wx.App()
    HostBox(None, -1, 'Oskar Stridsman\'s IT Resource: HostBox SSH Scanner')

    skipacc = False
    skipsrv = False
    infile = ""
    hostlist = []

    try:
        opts,args = getopt.getopt(argv,"hi:u:p:12",["ifile=","ufile=","pfile="])
        print opts,args
        if opts == []:
            app.MainLoop()

        else:
            for opt, arg in opts:
                if opt == '-h':
                    printHelp()
                    sys.exit()
                elif opt in ("-i", "--ifile="):
                    infile = arg

                elif opt in ("-u", "--ufile="):
                    usernames = arg

                elif opt in ("-p", "--pfile="):
                    passwords = arg

                elif opt in ("-1"):
                    skipacc = True
                elif opt in ("-2"):
                    skipsrv = True



            if infile == "":
                printHelp()
                sys.exit()
            if usernames == "":
                printHelp()
                sys.exit()
            if passwords == "":
                printHelp()
                sys.exit()


            fobject = open(infile, "r")
            hostlines = fobject.readlines()

            if "# Nmap" in hostlines[0]:
                succimport = False
                for l in hostlines:
                    if "Ports: 22/open/" in l:
                       ip = l.split(' ')
                       hostlist.append(ip[1])
                       succimport = True
                if succimport == False:
                    print 'No open ssh ports found in the selected iplist (or not a greppable nmap log!'
                    sys.exit()



            else:
                for lines in hostlines:
                    lines = lines.strip('\n')
                    hostlist.append(lines)


            consoleScan(hostlist,usernames,passwords,skipacc,skipsrv)

    except getopt.GetoptError:
        printHelp()
        sys.exit(2)






if __name__ == "__main__":
    main(sys.argv[1:])

