diff --git a/build.gradle b/build.gradle index ca99e44..6b615cb 100755 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,6 @@ apply plugin: 'application' mainClassName = "org.koreops.tauro.cli.TauroMain" dependencies { - testCompile 'junit:junit:' + libraryVersions.junit compile 'commons-cli:commons-cli:' + libraryVersions.commonsCli compile('org.k0r0pt:netutils:' + libraryVersions.netutils) { changing = true @@ -19,4 +18,8 @@ dependencies { compile('org.k0r0pt.routers:romdecoder:' + libraryVersions.romdecoder) { changing = true } + + testCompile 'junit:junit:' + libraryVersions.junit + testCompile 'org.codehaus.groovy:groovy-all:' + libraryVersions.groovy + testCompile 'org.spockframework:spock-core:' + libraryVersions.spock } diff --git a/dependencies.gradle b/dependencies.gradle index cba62be..845760f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,9 +1,11 @@ ext { libraryVersions = [ commonsCli : '1.4', - junit : '4.12', netutils : '1.0.0', tauroCore : '1.0.0', - romdecoder : '1.0.0' + romdecoder : '1.0.0', + junit : '4.12', + groovy : '2.4.15', + spock : '1.2-groovy-2.4', ] } \ No newline at end of file diff --git a/src/main/java/org/koreops/tauro/cli/dao/UpdaterDao.java b/src/main/java/org/koreops/tauro/cli/dao/UpdaterDao.java index 1d5e845..573e36b 100755 --- a/src/main/java/org/koreops/tauro/cli/dao/UpdaterDao.java +++ b/src/main/java/org/koreops/tauro/cli/dao/UpdaterDao.java @@ -15,7 +15,6 @@ package org.koreops.tauro.cli.dao; -import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -33,6 +32,13 @@ public class UpdaterDao { private static String isp; + public static final String FIND_STATION_SQL_STATEMENT = + "Select * from WirelessStations where lower(BSSID) = lower(?) and SSID = ?"; + public static final String UPDATE_STATION_SQL_STATEMENT = + "Update WirelessStations set Protocol = ?, Key = ?, ISP = ?, Phone = ? where BSSID = ? and SSID = ?"; + public static final String INSERT_STATION_SQL_STATEMENT = + "Insert into WirelessStations(BSSID, SSID, Protocol, Key, ISP, Phone) values(?, ?, ?, ?, ?, ?)"; + /** * Saves scraped Wifi station to the database. * @@ -40,14 +46,10 @@ public class UpdaterDao { * @param host The Host for which the data is being saved (Will be used for logging purposes) * @throws DbDriverException In case of a JDBC Driver related problem (unlikely to happen). */ - public static synchronized void saveStation(Map wifiData, String host) throws DbDriverException { + public static synchronized void saveStation(Map wifiData, String host, Connection conn) throws DbDriverException { try { boolean stationExists; - Connection conn; - conn = DbConnEngine.getConnection(); - String sql; - sql = "Select * from WirelessStations where lower(BSSID) = lower(?) and SSID = ?"; - PreparedStatement stmt = conn.prepareStatement(sql); + PreparedStatement stmt = conn.prepareStatement(FIND_STATION_SQL_STATEMENT); stmt.setString(1, wifiData.get("BSSID")); stmt.setString(2, wifiData.get("SSID")); ResultSet rs = stmt.executeQuery(); @@ -56,8 +58,7 @@ public static synchronized void saveStation(Map wifiData, String stmt.close(); if (stationExists) { - sql = "Update WirelessStations set Protocol = ?, Key = ?, ISP = ?, Phone = ? where BSSID = ? and SSID = ?"; - PreparedStatement stmt0 = conn.prepareStatement(sql); + PreparedStatement stmt0 = conn.prepareStatement(UPDATE_STATION_SQL_STATEMENT); String protocol = null; if ((wifiData.get("AuthType") != null) && (wifiData.get("Encryption") != null)) { // Protected network. @@ -79,8 +80,7 @@ public static synchronized void saveStation(Map wifiData, String stmt0.execute(); Logger.info(host + ": " + wifiData.get("BSSID") + " - " + wifiData.get("SSID") + " updated..."); } else { - sql = "Insert into WirelessStations(BSSID, SSID, Protocol, Key, ISP, Phone) values(?, ?, ?, ?, ?, ?)"; - PreparedStatement stmt0 = conn.prepareStatement(sql); + PreparedStatement stmt0 = conn.prepareStatement(INSERT_STATION_SQL_STATEMENT); String protocol = null; if ((wifiData.get("AuthType") != null) && (wifiData.get("Encryption") != null)) { // Protected network. diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/BinatoneScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/BinatoneScraper.java index abc8da4..7d505de 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/BinatoneScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/BinatoneScraper.java @@ -25,6 +25,7 @@ import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; import org.koreops.tauro.cli.scraper.exception.WirelessDisabledException; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -87,7 +88,7 @@ private boolean logWirelessStation(String hostUrl, String base64Login) throws Db } for (Map wifiData : wifiDataList) { - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); } } catch (WirelessDisabledException ex) { Logger.error(host + ex.getMessage()); diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/CoshipScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/CoshipScraper.java index 3a0bb83..06778e3 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/CoshipScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/CoshipScraper.java @@ -32,6 +32,7 @@ import org.koreops.net.def.beans.AuthCrackParams; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -102,7 +103,7 @@ private boolean logCoshipStation() throws DbDriverException { List> wifiDataList = this.fetchDetails(macAddr); for (Map m : wifiDataList) { - UpdaterDao.saveStation(m, host); + UpdaterDao.saveStation(m, host, DbConnEngine.getConnection()); } return true; } catch (IOException ex) { diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DLinkScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DLinkScraper.java index 2a40978..adab92f 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DLinkScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DLinkScraper.java @@ -24,6 +24,7 @@ import org.koreops.tauro.cli.authtrial.threads.DefaultAuthTrial; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -82,7 +83,7 @@ private boolean logDLinkWirelessStation(String hostUrl, String base64Login) thro } wifiData.put("BSSID", macAddr.toLowerCase()); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); return true; } catch (HttpStatusException ex) { if ((ex.getStatusCode() != 404) && (ex.getStatusCode() != 501)) { diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DigiflipScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DigiflipScraper.java index 0891854..5319bbf 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DigiflipScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/DigiflipScraper.java @@ -26,6 +26,7 @@ import org.koreops.net.def.beans.AuthCrackParams; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -199,7 +200,7 @@ private boolean logNewDigiflip(HtmlPage mainPage) throws IOException, Interrupte Logger.info(host + ": Found AuthType: " + wifiData.get("AuthType")); Logger.info(host + ": Found Encryption: " + wifiData.get("Encryption")); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); return true; } @@ -276,7 +277,7 @@ private boolean logOldDigiflip(HtmlPage mainPage) throws IOException, Interrupte Logger.info(host + ": Found AuthType: " + wifiData.get("AuthType")); Logger.info(host + ": Found Encryption: " + wifiData.get("Encryption")); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); return true; } diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/IBallWrx300NScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/IBallWrx300NScraper.java index 7d4b153..301bb35 100644 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/IBallWrx300NScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/IBallWrx300NScraper.java @@ -24,6 +24,7 @@ import org.koreops.tauro.cli.authtrial.threads.DefaultAuthTrial; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -109,7 +110,7 @@ private boolean logIBallBatonWirelessStation(String hostUrl, String base64Login) wifiData.put("BSSID", macAddr.toLowerCase()); wifiData.put("SSID", ssid); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); return true; } catch (HttpStatusException ex) { if ((ex.getStatusCode() != 404) && (ex.getStatusCode() != 501)) { diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewIBallBatonScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewIBallBatonScraper.java index eeb9450..9e19274 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewIBallBatonScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewIBallBatonScraper.java @@ -24,6 +24,7 @@ import org.koreops.tauro.cli.authtrial.threads.DefaultAuthTrial; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -96,7 +97,7 @@ private boolean logIBallBatonWirelessStation(String hostUrl, String base64Login) } wifiData.put("BSSID", macAddr.toString().toLowerCase()); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); return true; } catch (HttpStatusException ex) { if ((ex.getStatusCode() != 404) && (ex.getStatusCode() != 501)) { diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewTpLinkScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewTpLinkScraper.java index e954f82..dfc68c3 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewTpLinkScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/NewTpLinkScraper.java @@ -26,6 +26,7 @@ import org.koreops.net.def.beans.AuthCrackParams; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -213,7 +214,7 @@ private boolean logNewTpLinkStation() throws DbDriverException { Logger.info(host + ": Found AuthType: " + wifiData.get("AuthType")); Logger.info(host + ": Found Encryption: " + wifiData.get("Encryption")); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); return true; } catch (IOException ex) { diff --git a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/TpLinkScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/TpLinkScraper.java index 815515a..fc2b841 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/basicauth/TpLinkScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/basicauth/TpLinkScraper.java @@ -26,6 +26,7 @@ import org.koreops.net.def.beans.AuthCrackParams; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -201,7 +202,7 @@ private boolean logNewTpLinkStation() throws DbDriverException { Logger.info(host + ": Found AuthType: " + wifiData.get("AuthType")); Logger.info(host + ": Found Encryption: " + wifiData.get("Encryption")); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); return true; } catch (IOException ex) { diff --git a/src/main/java/org/koreops/tauro/cli/scraper/formauth/ActBeamScraper.java b/src/main/java/org/koreops/tauro/cli/scraper/formauth/ActBeamScraper.java index 996e28e..aee0a53 100755 --- a/src/main/java/org/koreops/tauro/cli/scraper/formauth/ActBeamScraper.java +++ b/src/main/java/org/koreops/tauro/cli/scraper/formauth/ActBeamScraper.java @@ -23,6 +23,7 @@ import org.koreops.net.def.beans.AuthCrackParams; import org.koreops.tauro.cli.dao.UpdaterDao; import org.koreops.tauro.cli.scraper.AbstractScraper; +import org.koreops.tauro.core.db.DbConnEngine; import org.koreops.tauro.core.exceptions.DbDriverException; import org.koreops.tauro.core.loggers.Logger; @@ -194,7 +195,7 @@ private boolean logActBeamWifi() throws DbDriverException { Logger.info(host + ": Found SSID: " + wifiData.get("SSID")); Logger.info(host + ": Found AuthType: " + wifiData.get("AuthType")); Logger.info(host + ": Found Encryption: " + wifiData.get("Encryption")); - UpdaterDao.saveStation(wifiData, host); + UpdaterDao.saveStation(wifiData, host, DbConnEngine.getConnection()); } return true; diff --git a/src/test/groovy/org/koreops/tauro/cli/dao/UpdaterDaoTest.groovy b/src/test/groovy/org/koreops/tauro/cli/dao/UpdaterDaoTest.groovy new file mode 100644 index 0000000..d01431e --- /dev/null +++ b/src/test/groovy/org/koreops/tauro/cli/dao/UpdaterDaoTest.groovy @@ -0,0 +1,136 @@ +package org.koreops.tauro.cli.dao + +import spock.lang.Shared +import spock.lang.Specification +import spock.lang.Unroll + +import java.sql.Connection +import java.sql.PreparedStatement +import java.sql.ResultSet + +class UpdaterDaoTest extends Specification { + + @Shared + def SSID_VALUE = "H4ckMe" + @Shared + def BSSID_VALUE = "66:66:66:66:66:66" + @Shared + def HOST = "dummy_host" + @Shared + def WPA_AUTH_TYPE = "WPA" + @Shared + def OPEN_AUTH_TYPE = "OPEN" + @Shared + def ENCRYPTION = "AES" + @Shared + def KEY = "123456" + @Shared + def PHONE = "123456" + @Shared + def ISP = "deutsche telekom" + + @Shared + def WIFI_DATA = ["SSID": SSID_VALUE, "BSSID": BSSID_VALUE, "key": KEY, "Phone": PHONE] + + @Shared + def STATION_EXISTS = true + + @Shared + def STATION_DOES_NOT_EXIST = false + + @Shared + def PROTECTED_NETWORK_WIFI_DATA = ["AuthType": WPA_AUTH_TYPE, "Encryption": ENCRYPTION] + WIFI_DATA + + @Shared + def OPEN_NETWORK_WIFI_DATA = ["AuthType": OPEN_AUTH_TYPE] + WIFI_DATA + + + def "test that the prepared statement responsible for finding a station is correctly assembled"() { + given: "a record of a station in the db" + def findStationResult = Mock(ResultSet) { + next() >> STATION_EXISTS + } + def findStationPreparedStatement = Mock(PreparedStatement) { + 1 * executeQuery() >> findStationResult + } + def dbConnection = Mock(Connection) { + prepareStatement(UpdaterDao.FIND_STATION_SQL_STATEMENT) >> findStationPreparedStatement + prepareStatement(UpdaterDao.UPDATE_STATION_SQL_STATEMENT) >> Mock(PreparedStatement) + } + when: "an attempt to save a station to the db is made" + UpdaterDao.saveStation(WIFI_DATA, HOST, dbConnection) + then: "the prepared statement is correctly assembled with the rught arguments" + 1 * findStationPreparedStatement.setString(1, BSSID_VALUE) + 1 * findStationPreparedStatement.setString(2, SSID_VALUE) + 2 * findStationPreparedStatement.close() // this should be called only once + 1 * findStationResult.close() + } + + @Unroll + def "Test that an existing station is correctly updated for a #description"() { + given: + def findStationResult = Mock(ResultSet) { + next() >> STATION_EXISTS + } + def findStationPreparedStatement = Mock(PreparedStatement) { + executeQuery() >> findStationResult + } + def updateStationPreparedStatement = Mock(PreparedStatement) + + def dbConnection = Mock(Connection) { + prepareStatement(UpdaterDao.FIND_STATION_SQL_STATEMENT) >> findStationPreparedStatement + prepareStatement(UpdaterDao.UPDATE_STATION_SQL_STATEMENT) >> updateStationPreparedStatement + } + when: + UpdaterDao.setIsp(ISP) + UpdaterDao.saveStation(wifiData, HOST, dbConnection) + then: + 1 * updateStationPreparedStatement.setString(1, expectedProtocol) + 1 * updateStationPreparedStatement.setString(2, KEY) + 1 * updateStationPreparedStatement.setString(3, ISP) + 1 * updateStationPreparedStatement.setString(4, PHONE) + 1 * updateStationPreparedStatement.setString(5, BSSID_VALUE.uncapitalize()) + 1 * updateStationPreparedStatement.setString(6, SSID_VALUE) + 1 * updateStationPreparedStatement.execute() + 1 * dbConnection.close() + 2 * findStationPreparedStatement.close() + where: + wifiData || expectedProtocol | description + PROTECTED_NETWORK_WIFI_DATA || "$WPA_AUTH_TYPE $ENCRYPTION" | "protected network" + OPEN_NETWORK_WIFI_DATA || OPEN_AUTH_TYPE | "open network" + } + + @Unroll + def "Test that a station is inserted for a #description"() { + given: + def findStationResult = Mock(ResultSet) { + next() >> STATION_DOES_NOT_EXIST + } + def findStationPreparedStatement = Mock(PreparedStatement) { + executeQuery() >> findStationResult + } + def updateStationPreparedStatement = Mock(PreparedStatement) + + def dbConnection = Mock(Connection) { + prepareStatement(UpdaterDao.FIND_STATION_SQL_STATEMENT) >> findStationPreparedStatement + prepareStatement(UpdaterDao.INSERT_STATION_SQL_STATEMENT) >> updateStationPreparedStatement + } + UpdaterDao.setIsp(ISP) + when: + UpdaterDao.saveStation(wifiData, HOST, dbConnection) + then: + 1 * updateStationPreparedStatement.setString(1, BSSID_VALUE.uncapitalize()) + 1 * updateStationPreparedStatement.setString(2, SSID_VALUE) + 1 * updateStationPreparedStatement.setString(3, expectedProtocol) + 1 * updateStationPreparedStatement.setString(4, KEY) + 1 * updateStationPreparedStatement.setString(5, ISP) + 1 * updateStationPreparedStatement.setString(6, PHONE) + 1 * updateStationPreparedStatement.execute() + 1 * dbConnection.close() + 2 * findStationPreparedStatement.close() + where: + wifiData || expectedProtocol | description + PROTECTED_NETWORK_WIFI_DATA || "$WPA_AUTH_TYPE $ENCRYPTION" | "protected network" + OPEN_NETWORK_WIFI_DATA || OPEN_AUTH_TYPE | "open network" + } +}