diff --git a/data/gui/msfgui.jar b/data/gui/msfgui.jar index 903a90ac92..42ae6d84e4 100644 Binary files a/data/gui/msfgui.jar and b/data/gui/msfgui.jar differ diff --git a/external/source/gui/msfguijava/src/msfgui/MainFrame.form b/external/source/gui/msfguijava/src/msfgui/MainFrame.form index d447959092..94e5b89cb1 100644 --- a/external/source/gui/msfguijava/src/msfgui/MainFrame.form +++ b/external/source/gui/msfguijava/src/msfgui/MainFrame.form @@ -131,7 +131,7 @@ - + @@ -161,7 +161,7 @@ - + @@ -191,7 +191,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -251,7 +251,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -308,7 +308,7 @@ - + diff --git a/external/source/gui/msfguijava/src/msfgui/MainFrame.java b/external/source/gui/msfguijava/src/msfgui/MainFrame.java index c6e30fbcbf..8df848821e 100644 --- a/external/source/gui/msfguijava/src/msfgui/MainFrame.java +++ b/external/source/gui/msfguijava/src/msfgui/MainFrame.java @@ -5,7 +5,6 @@ package msfgui; import java.awt.Component; import java.awt.HeadlessException; -import javax.swing.JTable; import org.jdesktop.application.*; import java.awt.event.*; import java.io.*; @@ -26,7 +25,6 @@ import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; -import javax.swing.table.DefaultTableModel; import org.jdesktop.application.Task; import org.jdesktop.swingworker.SwingWorker; @@ -48,14 +46,8 @@ public class MainFrame extends FrameView { public MainFrame(SingleFrameApplication app) { super(app); MsfFrame.setLnF(); + connectRpc(); // Connect to RPC daemon initComponents(); - eventsPane = new javax.swing.JScrollPane(); - eventsTable = new MsfTable(new String [] { - "Host", "Created", "Updated", "Name", "Critical", "Username", "Info" - }); - eventsTable.setName("eventsTable"); // NOI18N - eventsPane.setViewportView(eventsTable); - tabbedPane.addTab("Events", eventsPane); // NOI18N sessionsTableModel = null; sessionWindowMap = new HashMap(); @@ -121,14 +113,22 @@ public class MainFrame extends FrameView { //Set up GUI, RPC connection, and recent modules setupSessionsPollTimer(); setupPopupMenus(); + if(rpcConn != null) + getModules(); MsfguiApp.fileChooser = new JFileChooser(); - connectRpc(); getFrame().addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { if(!MsfguiApp.shuttingDown && !confirmStop()) throw new RuntimeException("Closing aborted."); } }); + //Events pane + eventsPane = new javax.swing.JScrollPane(); + eventsTable = new MsfTable(rpcConn, new String [] {"Host", "Created", "Updated", "Name", "Critical", "Username", "Info" + }, "events", new String[]{"host","created_at","updated_at","name","critical","username", "info"}); + eventsTable.setName("eventsTable"); // NOI18N + eventsPane.setViewportView(eventsTable);// Create a scrollable text area + tabbedPane.addTab("Events", eventsPane); // NOI18N //Setup icon this.getFrame().setIconImage( resourceMap.getImageIcon("main.icon").getImage()); //Disable tabs by default @@ -147,6 +147,15 @@ public class MainFrame extends FrameView { } } MsfFrame.updateSizes(getFrame()); + // Setup table autoquery code + ((MsfTable)eventsTable).addAutoAdjuster(eventsPane); + ((MsfTable)hostsTable).addAutoAdjuster(hostsPane); + ((MsfTable)clientsTable).addAutoAdjuster(clientsPane); + ((MsfTable)servicesTable).addAutoAdjuster(servicesPane); + ((MsfTable)vulnsTable).addAutoAdjuster(vulnsPane); + ((MsfTable)notesTable).addAutoAdjuster(notesPane); + ((MsfTable)lootsTable).addAutoAdjuster(lootsPane); + ((MsfTable)credsTable).addAutoAdjuster(credsPane); } /** Before exit, check whether the daemon should be stopped or just the session terminated */ private boolean confirmStop() { @@ -490,33 +499,26 @@ nameloop: for (int i = 0; i < names.length; i++) { sessionsPane = new javax.swing.JScrollPane(); sessionsTable = new javax.swing.JTable(); hostsPane = new javax.swing.JScrollPane(); - hostsTable = new MsfTable(new String [] { - "Created", "Address", "Address6", "MAC", "Name", "State", "OS name", "OS flavor", "OS SP", "OS lang", "Updated", "Purpose", "Info" - }); + hostsTable = new MsfTable(rpcConn, new String [] {"Created", "Address", "Address6", "MAC", "Name", "State", "OS name", "OS flavor", "OS SP", "OS lang", "Updated", "Purpose", "Info"} + , "hosts",new String[]{"created_at", "address", "address6", "mac", "name", "state", "os_name", "os_flavor", "os_sp", "os_lang", "updated_at", "purpose", "info"}); clientsPane = new javax.swing.JScrollPane(); - clientsTable = new MsfTable(new String [] { - "Host", "UA String", "UA Name", "UA Ver", "Created", "Updated" - }); + clientsTable = new MsfTable(rpcConn, new String [] {"Host", "UA String", "UA Name", "UA Ver", "Created", "Updated"} + , "clients", new String[]{"host", "ua_string", "ua_name", "ua_ver", "created_at", "updated_at"}); servicesPane = new javax.swing.JScrollPane(); - servicesTable = new MsfTable(new String [] { - "Host", "Created", "Updated", "Port", "Proto", "State", "Name", "Info" - }); + servicesTable = new MsfTable(rpcConn, new String [] {"Host", "Created", "Updated", "Port", "Proto", "State", "Name", "Info"} + , "services", new String[]{"host", "created_at", "updated_at", "port", "proto", "state", "name", "info"}); vulnsPane = new javax.swing.JScrollPane(); - vulnsTable = new MsfTable(new String [] { - "Port", "Proto", "Time", "Host", "Name", "Refs" - }); + vulnsTable = new MsfTable(rpcConn, new String [] {"Port", "Proto", "Time", "Host", "Name", "Refs" + }, "vulns", new String[]{"port", "proto", "time", "host", "name", "refs"}); notesPane = new javax.swing.JScrollPane(); - notesTable = new MsfTable(new String [] { - "Time", "Host", "Service", "Type", "Data" - }); + notesTable = new MsfTable(rpcConn, new String [] {"Time", "Host", "Service", "Type", "Data" + }, "notes", new String[]{"time", "host", "service", "type", "data"}); lootsPane = new javax.swing.JScrollPane(); - lootsTable = new MsfTable(new String [] { - "Host", "Service", "Ltype", "Ctype", "Data", "Created", "Updated", "Name", "Info" - }); + lootsTable = new MsfTable(rpcConn,new String [] {"Host", "Service", "Ltype", "Ctype", "Data", "Created", "Updated", "Name", "Info" + }, "loots", new String[]{"host", "service", "ltype", "ctype", "data", "created_at", "updated_at", "name", "info"}); credsPane = new javax.swing.JScrollPane(); - credsTable = new MsfTable(new String [] { - "Host", "Time", "Port", "Proto", "Sname", "Type", "User", "Pass", "Active" - }); + credsTable = new MsfTable(rpcConn, new String [] {"Host", "Time", "Port", "Proto", "Sname", "Type", "User", "Pass", "Active" + }, "creds", new String[]{"host", "time", "port", "proto", "sname", "type", "user", "pass", "active"}); menuBar = new javax.swing.JMenuBar(); javax.swing.JMenu fileMenu = new javax.swing.JMenu(); connectRpcMenuItem = new javax.swing.JMenuItem(); @@ -1191,7 +1193,6 @@ nameloop: for (int i = 0; i < names.length; i++) { helpMenu.add(onlineHelpMenu); aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N - aboutMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F1, 0)); aboutMenuItem.setName("aboutMenuItem"); // NOI18N helpMenu.add(aboutMenuItem); @@ -1242,6 +1243,8 @@ nameloop: for (int i = 0; i < names.length; i++) { private void connectRpcMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectRpcMenuItemActionPerformed connectRpc(); + if(rpcConn != null) + getModules(); }//GEN-LAST:event_connectRpcMenuItemActionPerformed private void clearHistoryItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearHistoryItemActionPerformed @@ -1318,19 +1321,14 @@ nameloop: for (int i = 0; i < names.length; i++) { } try { //Now load data out of current workspace MsfguiApp.workspace = ((Map) rpcConn.execute("db.current_workspace")).get("workspace").toString(); - if(DraggableTabbedPane.isVisible(eventsTable)) - reAdd(eventsTable,(List) ((Map)rpcConn.execute("db.events",MsfguiApp.workspace)).get("events"), - new String[]{"host","created_at","updated_at","name","critical","username","info"}); - if(all || DraggableTabbedPane.isVisible(lootsTable)) - reAdd(lootsTable,(List) ((Map)rpcConn.execute("db.loots",MsfguiApp.workspace)).get("loots"), - new String[]{"host","service","ltype","ctype","data","created_at","updated_at","name","info"}); - reAddQuery(hostsTable,"hosts",new String[]{"created_at","address","address6","mac","name","state","os_name", - "os_flavor","os_sp","os_lang","updated_at","purpose","info"}, all); - reAddQuery(clientsTable,"clients",new String[]{"host","ua_string","ua_name","ua_ver","created_at","updated_at"}, all); - reAddQuery(servicesTable, "services", new String[]{"host","created_at","updated_at","port","proto","state","name","info"}, all); - reAddQuery(vulnsTable,"vulns",new String[]{"port","proto","time","host","name","refs"}, all); - reAddQuery(notesTable,"notes",new String[]{"time", "host", "service", "type", "data"}, all); - reAddQuery(credsTable,"creds",new String[]{"host", "time", "port", "proto", "sname", "type", "user", "pass", "active"}, all); + ((MsfTable)eventsTable).reAddQuery(all, 0); + ((MsfTable)lootsTable).reAddQuery(all, 0); + ((MsfTable)hostsTable).reAddQuery(all, 0); + ((MsfTable)clientsTable).reAddQuery(all, 0); + ((MsfTable)servicesTable).reAddQuery(all, 0); + ((MsfTable)vulnsTable).reAddQuery(all, 0); + ((MsfTable)notesTable).reAddQuery(all, 0); + ((MsfTable)credsTable).reAddQuery(all, 0); } catch (MsfException mex) { if(!mex.getMessage().equals("database not loaded")) mex.printStackTrace(); @@ -1440,7 +1438,7 @@ nameloop: for (int i = 0; i < names.length; i++) { reloadDb(false); if(evt.getKeyCode() != KeyEvent.VK_DELETE) return; - JTable tab = (JTable)evt.getSource(); + MsfTable tab = (MsfTable)evt.getSource(); for(int row : tab.getSelectedRows()){ try { HashMap map = new HashMap(); @@ -1451,7 +1449,7 @@ nameloop: for (int i = 0; i < names.length; i++) { MsfguiApp.showMessage(getFrame(), mex); } }//delete then readd - reAddQuery(tab,name+"s",colNames, true); + tab.reAddQuery(true, 0); } private void hostsTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_hostsTableKeyReleased tableDelCheck(evt,"host",new String[]{"created_at","address","address6","mac","name","state","os_name", @@ -1471,7 +1469,7 @@ nameloop: for (int i = 0; i < names.length; i++) { }//GEN-LAST:event_notesTableKeyReleased private void lootsTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_lootsTableKeyReleased - reAddQuery(lootsTable,"loots",new String[]{"host","service","ltype","ctype","data","created_at","updated_at","name","info"}, true); + ((MsfTable)lootsTable).reAddQuery(true, 0); }//GEN-LAST:event_lootsTableKeyReleased private void clientsTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_clientsTableKeyReleased @@ -1623,8 +1621,6 @@ nameloop: for (int i = 0; i < names.length; i++) { private void connectRpc() { //make new rpcConnection rpcConn = OpenConnectionDialog.getConnection(this); - if(rpcConn != null) - getModules(); } /** Attempts to start msfrpcd and connect to it.*/ @@ -1974,35 +1970,4 @@ nameloop: for (int i = 0; i < names.length; i++) { private final Icon[] busyIcons = new Icon[15]; private int busyIconIndex = 0; private JDialog aboutBox; - - /** Clear a table's contents, reenabling the tab, and replace with contents of data returned from a db call */ - private void reAddQuery(JTable table, String call, String[] cols, boolean force) { - if(!force && !DraggableTabbedPane.isVisible(table)) - return; //Don't re-add if not visible - try { - HashMap arg = new HashMap(); - arg.put("workspace", MsfguiApp.workspace); - List data = (List) ((Map)rpcConn.execute("db."+call,arg)).get(call); - if(data == null) - return; - reAdd(table, data, cols); - } catch (MsfException mex) { - mex.printStackTrace(); - if(mex.getMessage().equals("database not loaded")) - throw mex; - } - } - private void reAdd(JTable table, List data, String[] cols) throws MsfException { - DefaultTableModel mod = (DefaultTableModel) table.getModel(); - while (mod.getRowCount() > 0) - mod.removeRow(0); - for (Object dataObj : data) { - Object[] row = new Object[cols.length]; - for (int i = 0; i < cols.length; i++) - row[i] = ((Map) dataObj).get(cols[i]); - mod.addRow(row); - } - TableHelper.fitColumnWidths(mod, table); - DraggableTabbedPane.setTabComponentEnabled(table, true); - } } diff --git a/external/source/gui/msfguijava/src/msfgui/MsfTable.java b/external/source/gui/msfguijava/src/msfgui/MsfTable.java index 31fcabc7ed..78c748a8c8 100644 --- a/external/source/gui/msfguijava/src/msfgui/MsfTable.java +++ b/external/source/gui/msfguijava/src/msfgui/MsfTable.java @@ -1,12 +1,19 @@ package msfgui; +import java.awt.Component; import java.awt.Dimension; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.ScrollPaneConstants; +import javax.swing.table.DefaultTableModel; /** * Table customization defaults to non-editable, autosorted table with some preferences @@ -16,11 +23,17 @@ import javax.swing.ScrollPaneConstants; * @author scriptjunkie */ public class MsfTable extends javax.swing.JTable { + private final String[] dbNames; + private final String dbTable; + private final RpcConnection rpcConn; /** * Default constructor just takes column names * @param colnames The names of the columns in the table */ - public MsfTable(String[] colnames){ + public MsfTable(final RpcConnection rpcConn, String[] colnames, String dbTable, String[] dbNames){ + this.dbNames = dbNames; + this.dbTable = dbTable; + this.rpcConn = rpcConn; setModel(new javax.swing.table.DefaultTableModel(new Object [][] {}, colnames) { public Class getColumnClass(int columnIndex) { try{ @@ -60,4 +73,54 @@ public class MsfTable extends javax.swing.JTable { } } ); } + /** Automatically query more info on new data */ + public void addAutoAdjuster(final JScrollPane pane){ + //Add autoadjuster to get more DB info + pane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener(){ + public void adjustmentValueChanged(AdjustmentEvent evt) { + java.awt.Adjustable adj = evt.getAdjustable(); + if(evt.getValueIsAdjusting() || adj.getValue() + adj.getVisibleAmount() != adj.getMaximum()) + return; + Component source = ((Component)evt.getSource()); + while(!(source instanceof JScrollPane)) + source = source.getParent(); + int rowCount = getRowCount(); + if(rowCount == 0 || (getRowCount() % 100) != 0) + return; + reAddQuery(false, rowCount); + } + }); + } + + /** Clear a table's contents, reenabling the tab, and replace with contents of data returned from a db call */ + public void reAddQuery(boolean force, int offset) { + if(!force && !DraggableTabbedPane.isVisible(this)) + return; //Don't re-add if not visible + try { + HashMap arg = new HashMap(10); + arg.put("workspace", MsfguiApp.workspace); + arg.put("offset", offset); + List data = (List) ((Map)rpcConn.execute("db."+dbTable, arg)).get(dbTable); + if(data == null) + return; + DefaultTableModel mod = (DefaultTableModel) getModel(); + while (mod.getRowCount() > offset) + mod.removeRow(mod.getRowCount() - 1); + for (Object dataObj : data) { + Object[] row = new Object[dbNames.length]; + for (int i = 0; i < dbNames.length; i++){ + row[i] = ((Map) dataObj).get(dbNames[i]); + if(dbNames[i].endsWith("_at")) + row[i] = new java.util.Date(Long.parseLong(row[i].toString()) * 1000); + } + mod.addRow(row); + } + TableHelper.fitColumnWidths(mod, this); + DraggableTabbedPane.setTabComponentEnabled(this, true); + } catch (MsfException mex) { + mex.printStackTrace(); + if(mex.getMessage().equals("database not loaded")) + throw mex; + } + } } diff --git a/lib/msf/core/rpc/v10/rpc_db.rb b/lib/msf/core/rpc/v10/rpc_db.rb index e96380e432..e904a44808 100644 --- a/lib/msf/core/rpc/v10/rpc_db.rb +++ b/lib/msf/core/rpc/v10/rpc_db.rb @@ -9,7 +9,7 @@ private def find_workspace(wspace = nil) if(wspace and wspace != "") - return self.framework.db.find_workspace(wspace) + return self.framework.db.find_workspace(wspace) || error(500, "Invalid workspace") end self.framework.db.workspace end @@ -74,23 +74,29 @@ private error(500, "Database Not Loaded") if not db end + def init_db_opts_workspace(xopts) + db_check + opts = fix_options(xopts) + opts[:workspace] = find_workspace(opts[:workspace]) + return opts, opts[:workspace] + end + public def rpc_hosts(xopts) - - db_check - - opts = fix_options(xopts) + opts, wspace = init_db_opts_workspace(xopts) conditions = {} conditions[:state] = [Msf::HostState::Alive, Msf::HostState::Unknown] if opts[:only_up] conditions[:address] = opts[:addresses] if opts[:addresses] - wspace = find_workspace(opts[:workspace]) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 ret = {} ret[:hosts] = [] - wspace.hosts.all(:conditions => conditions, :order => :address).each do |h| + wspace.hosts.all(:conditions => conditions, :order => :address, + :limit => limit, :offset => offset).each do |h| host = {} host[:created_at] = h.created_at.to_i host[:address] = h.address.to_s @@ -111,48 +117,22 @@ public end def rpc_services( xopts) + opts, wspace = init_db_opts_workspace(xopts) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 - db_check - - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) - opts[:workspace] = wspace if opts[:workspace] - hosts = [] - - if opts[:addresses] - conditions = {} - conditions[:address] = opts[:addresses] if opts[:addresses] - hosts = wspace.hosts.all(:conditions => conditions, :order => :address) - elsif opts[:host] || opts[:address] - host = self.framework.db.get_host(opts) - hosts << host - end + conditions = {} + conditions[:state] = [ServiceState::Open] if opts[:only_up] + conditions[:proto] = opts[:proto] if opts[:proto] + conditions["hosts.address"] = opts[:addresses] if opts[:addresses] + conditions[:port] = Rex::Socket.portspec_to_portlist(opts[:ports]) if opts[:ports] + conditions[:name] = opts[:names].strip().split(",") if opts[:names] ret = {} ret[:services] = [] - a = self.framework.db.get_host(opts) - - services = [] - if opts[:host] || opts[:address] || opts[:addresses] - hosts.each do |host| - sret = nil - if(opts[:proto] && opts[:port]) - sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port]) - else - sret = host.services - end - next if sret == nil - services << sret if sret.class == Msf::DBManager::Service - services |= sret if sret.class == Array - end - else - services = wspace.services - end - - return ret if (not services) - - services.each do |s| + wspace.services.all(:include => :host, :conditions => conditions, + :limit => limit, :offset => offset).each do |s| service = {} host = s.host service[:host] = host.address || host.address6 || "unknown" @@ -168,79 +148,20 @@ public ret end - def rpc_vulns(xopts) - - db_check - - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) - opts[:workspace] = wspace if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 + + conditions = {} + conditions["hosts.address"] = opts[:addresses] if opts[:addresses] + conditions[:name] = opts[:names].strip().split(",") if opts[:names] + conditions["services.port"] = Rex::Socket.portspec_to_portlist(opts[:ports]) if opts[:port] + conditions["services.proto"] = opts[:proto] if opts[:proto] ret = {} ret[:vulns] = [] - hosts = [] - services = [] - vulns = [] - # Get Matching Hosts - if opts[:addresses] - conditions = {} - conditions[:address] = opts[:addresses] if opts[:addresses] - hosts = wspace.hosts.all(:conditions => conditions, :order => :address) - elsif opts[:host] || opts[:address] - host = self.framework.db.get_host(opts) - hosts << host - end - - #Get Matching Services - if opts[:host] || opts[:address] || opts[:addresses] - hosts.each do |host| - sret = nil - if(opts[:proto] && opts[:port]) - sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port]) - else - sret = host.services - end - next if sret == nil - services << sret if sret.class == Msf::DBManager::Service - services |= sret if sret.class == Array - end - elsif opts[:port] && opts[:proto] - sret = wspace.services.find_by_proto_and_port(opts[:proto],opts[:port]) - services << sret if sret.class == Msf::DBManager::Service - services |= sret if sret.class == Array - end - - #get list of vulns - if services.count > 0 - services.each do |s| - if opts[:name] - nret = s.vulns.find_by_name(opts[:name]) - else - nret = s.vulns - end - next if nret == nil - vulns << nret if nret.class == Msf::DBManager::Vuln - vulns |= nret if nret.class == Array - end - elsif hosts.count > 0 - hosts.each do |h| - if opts[:name] - nret = h.vulns.find_by_name(opts[:name]) - else - nret = h.vulns - end - next if nret == nil - vulns << nret if nret.class == Msf::DBManager::Vuln - vulns |= nret if nret.class == Array - end - else - nret = wspace.vulns - vulns << nret if nret.class == Msf::DBManager::Vuln - vulns |= nret if nret.class == Array - end - - vulns.each do |v| + wspace.vulns.all(:include => :service, :conditions => conditions, :limit => limit, :offset => offset).each do |v| vuln = {} reflist = v.refs.map { |r| r.name } if(v.service) @@ -330,12 +251,11 @@ public end def rpc_get_host(xopts) - db_check + opts, wspace = init_db_opts_workspace(xopts) ret = {} ret[:host] = [] opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] h = self.framework.db.get_host(opts) if(h) host = {} @@ -358,9 +278,7 @@ public end def rpc_report_host(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_host(opts) return { :result => 'success' } if(res) @@ -369,19 +287,14 @@ public end def rpc_report_service(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_service(opts) return { :result => 'success' } if(res) { :result => 'failed' } end def rpc_get_service(xopts) - db_check - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) - opts[:workspace] = wspace if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) ret = {} ret[:service] = [] @@ -425,10 +338,7 @@ public end def rpc_get_note(xopts) - db_check - - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) ret = {} ret[:note] = [] @@ -478,9 +388,7 @@ public end def rpc_get_client(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) ret = {} ret[:client] = [] c = self.framework.db.get_client(opts) @@ -499,9 +407,7 @@ public end def rpc_report_client(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_client(opts) return { :result => 'success' } if(res) { :result => 'failed' } @@ -509,9 +415,7 @@ public #DOC NOTE: :data and :ntype are REQUIRED def rpc_report_note(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) if (opts[:host] or opts[:address]) and opts[:port] and opts[:proto] addr = opts[:host] || opts[:address] wspace = opts[:workspace] || self.framework.db.workspace @@ -526,76 +430,21 @@ public end def rpc_notes(xopts) - db_check - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) if opts[:workspace] - opts[:workspace] = wspace + opts, wspace = init_db_opts_workspace(xopts) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 + + conditions = {} + conditions["hosts.address"] = opts[:addresses] if opts[:addresses] + conditions[:name] = opts[:names].strip().split(",") if opts[:names] + conditions[:ntype] = opts[:ntype] if opts[:ntype] + conditions["services.port"] = Rex::Socket.portspec_to_portlist(opts[:ports]) if opts[:port] + conditions["services.proto"] = opts[:proto] if opts[:proto] ret = {} ret[:notes] = [] - hosts = [] - services = [] - notes = [] - - # Get Matching Hosts - if opts[:addresses] - conditions = {} - conditions[:address] = opts[:addresses] if opts[:addresses] - hosts = wspace.hosts.all(:conditions => conditions, :order => :address) - elsif opts[:host] || opts[:address] - host = self.framework.db.get_host(opts) - hosts << host - end - - #Get Matching Services - if opts[:host] || opts[:address] || opts[:addresses] - hosts.each do |host| - sret = nil - if(opts[:proto] && opts[:port]) - sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port]) - else - sret = host.services - end - next if sret == nil - services << sret if sret.class == Msf::DBManager::Service - services |= sret if sret.class == Array - end - elsif opts[:port] && opts[:proto] - sret = wspace.services.find_by_proto_and_port(opts[:proto],opts[:port]) - services << sret if sret.class == Msf::DBManager::Service - services |= sret if sret.class == Array - end - - #get list of notes - if services.count > 0 - services.each do |s| - if opts[:ntype] - nret = s.notes.find_by_ntype(opts[:ntype]) - else - nret = s.notes - end - next if nret == nil - notes << nret if nret.class == Msf::DBManager::Note - notes |= nret if nret.class == Array - end - elsif hosts.count > 0 - hosts.each do |h| - if opts[:ntype] - nret = h.notes.find_by_ntype(opts[:ntype]) - else - nret = h.notes - end - next if nret == nil - notes << nret if nret.class == Msf::DBManager::Note - notes |= nret if nret.class == Array - end - else - nret = wspace.notes - notes << nret if nret.class == Msf::DBManager::Note - notes |= nret if nret.class == Array - end - - notes.each do |n| + wspace.notes.all(:include => [:host, :service], :conditions => conditions, + :limit => limit, :offset => offset).each do |n| note = {} note[:time] = n.created_at.to_i note[:host] = "" @@ -610,18 +459,14 @@ public end def rpc_report_auth_info(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_auth_info(opts) return { :result => 'success' } if(res) { :result => 'failed' } end def rpc_get_auth_info(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) ret = {} ret[:auth_info] = [] ai = self.framework.db.get_auth_info(opts) @@ -641,9 +486,7 @@ public end def rpc_del_vuln(xopts) - db_check - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) + opts, wspace = init_db_opts_workspace(xopts) hosts = [] services = [] vulns = [] @@ -710,9 +553,7 @@ public end def rpc_del_note(xopts) - db_check - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) + opts, wspace = init_db_opts_workspace(xopts) hosts = [] services = [] notes = [] @@ -778,9 +619,7 @@ public end def rpc_del_service(xopts) - db_check - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) + opts, wspace = init_db_opts_workspace(xopts) hosts = [] services = [] if opts[:host] or opts[:address] @@ -860,7 +699,6 @@ public return { :result => 'success', :deleted => deleted } end - def rpc_report_vuln(xopts) db_check opts = fix_options(xopts) @@ -870,15 +708,15 @@ public { :result => 'failed' } end + def rpc_events(xopts) + opts, wspace = init_db_opts_workspace(xopts) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 - def rpc_events(wspace = nil) - db_check - wspace = find_workspace(wspace) - error(500, "Unknown Workspace") if(not wspace) ret = {} ret[:events] = [] - self.framework.db.events(wspace).each do |e| + wspace.events.all(:limit => limit, :offset => offset).each do |e| event = {} event[:host] = e.host.address || e.host.address6 if(e.host) event[:created_at] = e.created_at.to_i @@ -893,9 +731,7 @@ public end def rpc_report_event(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_event(opts) { :result => 'success' } if(res) end @@ -903,8 +739,7 @@ public #NOTE Path is required #NOTE To match a service need host, port, proto def rpc_report_loot(xopts) - db_check - opts = fix_options(xopts) + opts, wspace = init_db_opts_workspace(xopts) if opts[:host] && opts[:port] && opts[:proto] opts[:service] = self.framework.db.find_or_create_service(opts) end @@ -913,14 +748,14 @@ public { :result => 'success' } if(res) end - def rpc_loots(wspace=nil) - db_check - wspace = find_workspace(wspace) - error(500, "Unknown Workspace") if(not wspace) - + def rpc_loots(xopts) + opts, wspace = init_db_opts_workspace(xopts) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 + ret = {} ret[:loots] = [] - self.framework.db.loots(wspace).each do |l| + wspace.loots.all(:limit => limit, :offset => offset).each do |l| loot = {} loot[:host] = l.host.address || l.host.address6 if(l.host) loot[:service] = l.service.name || n.service.port if(n.service) @@ -938,8 +773,7 @@ public # requires host, port, user, pass, ptype, and active def rpc_report_cred(xopts) - db_check - opts = fix_options(xopts) + opts, wspace = init_db_opts_workspace(xopts) res = framework.db.find_or_create_cred(opts) return { :result => 'success' } if res { :result => 'failed' } @@ -947,15 +781,17 @@ public #right now workspace is the only option supported def rpc_creds(xopts) - db_check - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) + opts, wspace = init_db_opts_workspace(xopts) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 + ret = {} ret[:creds] = [] - self.framework.db.creds(wspace).each do |c| + DBManager::Cred.find(:all, :include => {:service => :host}, :conditions => ["hosts.workspace_id = ?", + framework.db.workspace.id ], :limit => limit, :offset => offset).each do |c| cred = {} cred[:host] = c.service.host.address || c.service.host.address6 if(c.service.host) - cred[:time] = c.updated_at + cred[:updated_at] = c.updated_at.to_i cred[:port] = c.service.port cred[:proto] = c.service.proto cred[:sname] = c.service.name @@ -969,17 +805,13 @@ public end def rpc_import_data(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) self.framework.db.import(opts) return { :result => 'success' } end def rpc_get_vuln(xopts) - db_check - opts = fix_options(xopts) - opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] + opts, wspace = init_db_opts_workspace(xopts) ret = {} ret[:vuln] = [] @@ -1027,35 +859,20 @@ public end def rpc_clients(xopts) - db_check - opts = fix_options(xopts) - wspace = find_workspace(opts[:workspace]) - hosts = [] - clients = [] + opts, wspace = init_db_opts_workspace(xopts) + limit = opts.delete(:limit) || 100 + offset = opts.delete(:offset) || 0 + + conditions = {} + conditions[:ua_name] = opts[:ua_name] if opts[:ua_name] + conditions[:ua_ver] = opts[:ua_ver] if opts[:ua_ver] + conditions["hosts.address"] = opts[:addresses] if opts[:addresses] + ret = {} ret[:clients] = [] - if opts[:host] or opts[:address] or opts[:addresses] - hosts = opts_to_hosts(opts) - else - hosts = wspace.hosts - end - - hosts.each do |h| - cret = nil - if opts[:ua_name] or opts[:ua_ver] - conditions = {} - conditions[:ua_name] = opts[:ua_name] if opts[:ua_name] - conditions[:ua_ver] = opts[:ua_ver] if opts[:ua_ver] - cret = h.clients.all(:conditions => conditions) - else - cret = h.clients - end - next if cret == nil - clients << cret if cret.class == Msf::DBManager::Client - clients |= cret if cret.class == Array - end - clients.each do |c| + wspace.clients.all(:include => :host, :conditions => conditions, + :limit => limit, :offset => offset).each do |c| client = {} client[:host] = c.host.address.to_s if c.host client[:ua_string] = c.ua_string