This commit is contained in:
Niklas 2017-07-14 00:27:33 +02:00
parent 2da318ef44
commit 6572a3d317
8 changed files with 821 additions and 77 deletions

58
pom.xml
View File

@ -7,19 +7,6 @@
<groupId>de.gurkengewuerz</groupId> <groupId>de.gurkengewuerz</groupId>
<artifactId>postfix-rest-send</artifactId> <artifactId>postfix-rest-send</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.simplejavamail</groupId> <groupId>org.simplejavamail</groupId>
@ -46,5 +33,50 @@
<artifactId>json</artifactId> <artifactId>json</artifactId>
<version>20170516</version> <version>20170516</version>
</dependency> </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<finalName>${project.artifactId}</finalName>
<descriptorRefs>
<descriptorRef>
jar-with-dependencies
</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>${project.groupId}.postfix_rest_send.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>assamble</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -0,0 +1,136 @@
package de.gurkengewuerz.postfix_rest_send;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by gurkengewuerz.de on 02.07.2017.
*/
public class Config extends JSONObject {
private File file;
private JSONObject database;
private boolean firstRun = false;
public Config(File file) throws IOException {
this.file = file;
if (!file.exists()) {
file.createNewFile();
firstRun = true;
}
if (!file.isFile()) {
throw new FileNotFoundException(file.getAbsolutePath() + " not found");
}
if (!file.canRead() || !file.canWrite()) {
throw new AccessDeniedException(file.getAbsolutePath() + " is not accessable");
}
this.put("debug", true);
this.put("disable_bruteforcefilter", false);
this.put("token_expire", 730); // houres/1M
this.put("http_port", 8081);
this.put("postfixadmin_encryption", "md5crypt");
this.put("postfixadmin_path", "/var/www/html/postfixadmin/");
JSONObject database = new JSONObject();
database.put("port", 3306);
database.put("host", "127.0.0.1");
database.put("db", "mail");
database.put("username", "postfixadmin");
database.put("password", "abc123");
this.put("database", database);
}
public void save() {
try {
FileWriter fw = new FileWriter(file.getAbsolutePath());
fw.write(this.toString(4));
fw.close();
loadRestData();
} catch (IOException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
}
}
public void load() {
try {
String content = new String(Files.readAllBytes(file.toPath()), "UTF-8");
if (content.isEmpty()) {
save();
return;
}
JSONTokener jt = new JSONTokener(content);
if (jt.nextClean() != 123) {
throw jt.syntaxError("A JSONObject text must begin with '{'");
} else {
while (jt.more()) {
char c = jt.nextClean();
switch (c) {
case '\u0000':
throw jt.syntaxError("A JSONObject text must end with '}'");
case '}':
return;
default:
jt.back();
String key = jt.nextValue().toString();
c = jt.nextClean();
if (c != 58) {
throw jt.syntaxError("Expected a ':' after a key");
}
this.remove(key);
this.putOnce(key, jt.nextValue());
switch (jt.nextClean()) {
case ',':
case ';':
if (jt.nextClean() == 125) {
return;
}
jt.back();
break;
case '}':
save();
return;
default:
throw jt.syntaxError("Expected a ',' or '}'");
}
}
}
}
} catch (IOException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
}
}
public boolean debug() {
return getBoolean("debug");
}
private void loadRestData() {
database = getJSONObject("database");
}
public JSONObject getDatabaseConfig() {
return database;
}
public String getDBURL() {
return "jdbc:mysql://" + getDatabaseConfig().getString("host") + ":" + getDatabaseConfig().getInt("port") + "/" + getDatabaseConfig().getString("db");
}
public boolean isFirstRun() {
return firstRun;
}
}

View File

@ -1,104 +1,254 @@
package de.gurkengewuerz.postfix_rest_send; package de.gurkengewuerz.postfix_rest_send;
import de.gurkengewuerz.postfix_rest_send.objects.BruteforceFilter;
import de.gurkengewuerz.postfix_rest_send.objects.ReturnHolder;
import de.gurkengewuerz.postfix_rest_send.utils.BashUtils;
import de.gurkengewuerz.postfix_rest_send.utils.HtmlToPlainText;
import de.gurkengewuerz.postfix_rest_send.utils.RandomUtils;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import org.hazlewood.connor.bottema.emailaddress.EmailAddressCriteria;
import org.hazlewood.connor.bottema.emailaddress.EmailAddressValidator;
import org.json.JSONObject; import org.json.JSONObject;
import org.simplejavamail.email.Email;
import org.simplejavamail.mailer.Mailer;
import org.simplejavamail.mailer.config.ServerConfig;
import java.io.BufferedReader; import javax.mail.Message;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* Created by gurkengewuerz.de on 12.07.2017. * Created by gurkengewuerz.de on 12.07.2017.
*/ */
public class Main extends NanoHTTPD { public class Main extends NanoHTTPD {
private static MySQL db;
private static Config conf;
private static Mailer mailer;
private static BruteforceFilter filter;
/*
TODO:
Main umbennen
Configurierbare Domains/IPs
Post JSON Support
*/
public Main() throws IOException { public Main() throws IOException {
super(8081); super(conf.getInt("http_port"));
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Started Server :" + getListeningPort());
start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
} }
// http://www.simplejavamail.org/#/debugging public static void main(String[] args) throws IOException, SQLException {
String settingsFile = "." + File.separator + "settings.json";
public static void main(String[] args) { if (args.length >= 1) {
// Mailer m = new Mailer(new ServerConfig("localhost", 25)); settingsFile = args[0];
// m.setDebug(true);
//
// Email email = new Email();
// email.setFromAddress("admin@gurkengewuerz.de", "admin@gurkengewuerz.de");
// email.setReplyToAddress("support@gurkengewuerz.de", "support@gurkengewuerz.de");
// email.addRecipient("developer@the-town.net", "developer@the-town.net", Message.RecipientType.TO);
// email.setSubject("Email Test");
// email.setText("Dies ist ein Email Test von Java.\nHoffentlich bald mit Rest API");
// email.setTextHTML("<img src='cid:wink1'><b>We should meet up!</b><img src='cid:wink2'>");
//
// m.sendMail(email);
// HtmlToPlainText formatter = new HtmlToPlainText();
// formatter.getPlainText()
try {
System.out.println("Started");
new Main();
} catch (IOException e) {
e.printStackTrace();
} }
File f = new File(settingsFile);
conf = new Config(f);
conf.load();
if (conf.debug())
Logger.getLogger(Main.class.getName()).log(Level.INFO, "Using Settingsfile " + f.getAbsolutePath());
if (conf.isFirstRun()) System.exit(0);
db = new MySQL(MySQL.Type.MYSQL, conf.getDBURL(), conf.getDatabaseConfig().getString("username"), conf.getDatabaseConfig().getString("password"));
db.executeUpdate("CREATE TABLE IF NOT EXISTS token (" +
" tokenid int(11) NOT NULL AUTO_INCREMENT," +
" username VARCHAR(255) NOT NULL," +
" token VARCHAR(255) NOT NULL," +
" created INT NOT NULL," +
" expire INT NOT NULL," +
" PRIMARY KEY (tokenid), " +
" UNIQUE (token)" +
" ); ");
db.executeUpdate("CREATE TABLE IF NOT EXISTS token_bruteforce (" +
" id int(11) NOT NULL AUTO_INCREMENT," +
" occurred INT NOT NULL," +
" ip VARCHAR(255) NOT NULL," +
" PRIMARY KEY (id)" +
" ); ");
mailer = new Mailer(new ServerConfig("localhost", 25));
mailer.setDebug(conf.debug());
filter = new BruteforceFilter(6);
new Main();
} }
@Override @Override
public Response serve(IHTTPSession session) { public Response serve(IHTTPSession session) {
Map<String, String> headers = session.getHeaders();
String ip = headers.get("remote-addr");
Logger.getLogger(Main.class.getName()).log(Level.INFO, session.getMethod().name() + ": " + session.getUri() + " " + ip);
Map<String, String> parms = session.getParms(); Map<String, String> parms = session.getParms();
JSONObject json = new JSONObject("{'error':'not found'}"); JSONObject json = new JSONObject("{'error':'not found'}");
Response.Status status = Response.Status.NOT_FOUND; Response.Status status = Response.Status.NOT_IMPLEMENTED;
if (filter.banned(ip))
return getError(Response.Status.FORBIDDEN, "you are temporary banned");
try {
if (session.getMethod().equals(Method.POST))
session.parseBody(parms);
} catch (IOException | ResponseException e) {
return getError(Response.Status.INTERNAL_ERROR);
}
if (db == null) return getError(Response.Status.INTERNAL_ERROR, "Database Error");
try {
if (session.getUri().startsWith("/authorize")) { if (session.getUri().startsWith("/authorize")) {
if (session.getUri().startsWith("/authorize/add")) { if (session.getUri().startsWith("/authorize/add")) {
String username = parms.get("username"); String username = parms.get("username");
String password = parms.get("password"); String password = parms.get("password");
if (username != null && password != null) { if (username == null || password == null) return getError(Response.Status.UNAUTHORIZED);
System.out.println(checkPassword("/var/www/html/tools/functions.inc.php", "md5", "EMailFam.Schuetrumpf@123", "460b7d128333a4be972d4c7bdb0ee142"));
boolean usernameValid = EmailAddressValidator.isValid(username, EnumSet.of(EmailAddressCriteria.ALLOW_DOMAIN_LITERALS));
status = Response.Status.OK; if (!usernameValid) {
json = new JSONObject("{'token':''}"); filter.failed(ip);
} else { return getError(Response.Status.UNAUTHORIZED, "invalid user");
json = new JSONObject("{'error':'username/password is null'}");
} }
} else if (session.getUri().startsWith("/authorize/revoke")) {
ResultSet rs = db.executeQuery("SELECT * FROM mailbox WHERE username = ? AND active = 1;", username);
int rowcount = 0;
while (rs.next()) {
rowcount++;
}
rs.beforeFirst();
rs.next();
if (rowcount <= 0) {
filter.failed(ip);
return getError(Response.Status.UNAUTHORIZED);
}
boolean correct = checkPassword(conf.getString("postfixadmin_encryption"), password, rs.getString("password"));
if (!correct) {
filter.failed(ip);
return getError(Response.Status.UNAUTHORIZED);
}
String token = RandomUtils.rndToken(username);
long expires = (System.currentTimeMillis() / 1000) + (conf.getInt("token_expire") * 60 * 60);
db.executeUpdate("INSERT INTO token (username, token, created, expire) VALUES (?,?,?,?);", username, token, (System.currentTimeMillis() / 1000), expires);
status = Response.Status.OK;
json = new JSONObject("{'token':'" + token + "', 'expires': " + expires + "}");
} else if (session.getUri().startsWith("/authorize/revoke")) {
String token = parms.get("token");
if (token == null) return getError(Response.Status.BAD_REQUEST);
db.executeUpdate("DELETE FROM token WHERE token = ?;", token);
status = Response.Status.OK;
json = new JSONObject("{'status':'ok'}");
} }
} else if (session.getUri().startsWith("/validate/address")) { } else if (session.getUri().startsWith("/validate/address")) {
String mail = parms.get("mail");
if (mail == null) return getError(Response.Status.BAD_REQUEST);
boolean valid = EmailAddressValidator.isValid(mail, EnumSet.of(EmailAddressCriteria.ALLOW_DOMAIN_LITERALS));
status = Response.Status.OK;
json = new JSONObject("{'valid':" + valid + "}");
} else if (session.getUri().startsWith("/send")) { } else if (session.getUri().startsWith("/send")) {
String token = parms.get("token");
String to = parms.get("to");
String subject = parms.get("to");
String text = parms.get("text");
String html = parms.get("html");
if (token == null) return getError(Response.Status.UNAUTHORIZED);
ResultSet rs = db.executeQuery("SELECT * FROM token WHERE token = ?;", token);
int rowcount = 0;
while (rs.next()) {
rowcount++;
}
rs.beforeFirst();
rs.next();
if (rowcount <= 0){
filter.banned(ip);
return getError(Response.Status.UNAUTHORIZED);
}
if (rs.getLong("expire") <= System.currentTimeMillis() / 1000)
return getError(Response.Status.UNAUTHORIZED, "token expired");
String username = rs.getString("username");
if (to == null || subject == null || (text == null && html == null))
return getError(Response.Status.BAD_REQUEST);
ArrayList<String> toList = new ArrayList<>();
if (to.contains(";")) {
for (String mailTo : to.split(";")) {
if (!EmailAddressValidator.isValid(mailTo, EnumSet.of(EmailAddressCriteria.ALLOW_DOMAIN_LITERALS)))
return getError(Response.Status.BAD_REQUEST, "invalid recipient");
toList.add(mailTo);
}
} else {
if (!EmailAddressValidator.isValid(to, EnumSet.of(EmailAddressCriteria.ALLOW_DOMAIN_LITERALS)))
return getError(Response.Status.BAD_REQUEST, "invalid recipient");
toList.add(to);
}
Email email = new Email();
email.setFromAddress(username, username);
toList.forEach(s -> email.addRecipient(s, s, Message.RecipientType.TO));
email.setSubject(subject);
if (text != null) email.setText(text);
if (html != null) email.setTextHTML(html);
if (text == null && html != null) {
HtmlToPlainText formatter = new HtmlToPlainText();
email.setText(formatter.getPlainText(html));
}
mailer.sendMail(email);
status = Response.Status.OK;
json = new JSONObject("{'status':'send'}");
}
} catch (SQLException e) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, e);
return getError(Response.Status.INTERNAL_ERROR);
} }
return newFixedLengthResponse(status, "application/json", json.toString()); return newFixedLengthResponse(status, "application/json", json.toString());
} }
public boolean checkPassword(String path, String encryption, String plain, String dbPW) { public boolean checkPassword(String encryption, String plain, String dbPW) {
String crypted = execPHP("-r '$CONF = array(); $CONF[\"encrypt\"] = \"" + encryption + "\"; include \"" + path + "\"; echo(pacrypt(\"" + plain + "\", \"" + dbPW + "\")).\"\\n\";'"); ReturnHolder crypted = BashUtils.run(conf.debug(), "php", "-r", "$CONF = array(); $CONF[\"encrypt\"] = \"" + encryption + "\"; include \"" + conf.getString("postfixadmin_path") + "/functions.inc.php" + "\"; echo(pacrypt(\"" + plain + "\", \"" + dbPW + "\")).\"\\n\";");
System.out.println(crypted); return String.join("", crypted.output).equals(dbPW);
return crypted.equals(dbPW);
} }
public String execPHP(String args) {
try { public Response getError(Response.Status status, String error) {
System.out.println(args); JSONObject json = new JSONObject("{'error':'unknown error'}");
String line; json.put("error", error);
StringBuilder output = new StringBuilder(); return newFixedLengthResponse(status, "application/json", json.toString());
Process p = Runtime.getRuntime().exec("php " + args);
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
output.append(line);
System.out.println(line);
} }
input.close();
return output.toString(); public Response getError(Response.Status status) {
} catch (Exception err) { switch (status) {
err.printStackTrace(); case INTERNAL_ERROR:
return getError(status, "internal server rror");
case BAD_REQUEST:
return getError(status, "bad request");
case UNAUTHORIZED:
return getError(status, "unauthorized");
} }
return ""; return getError(status, "unknown error");
}
public static MySQL getDatabase() {
return db;
}
public static Config getConfig() {
return conf;
} }
} }

View File

@ -0,0 +1,252 @@
package de.gurkengewuerz.postfix_rest_send;
import java.sql.*;
import java.util.logging.Logger;
/**
* Simple wrapper for database abstraction.
*
* @author Nijiko
* @url https://raw.githubusercontent.com/iConomy/SimpleShop/master/com/nijiko/simpleshop/database/Wrapper.java
*/
public class MySQL {
private static final Logger log = Logger.getLogger("MySQL");
/**
* Database Types
*/
public enum Type {
SQLITE,
MYSQL
}
;
/**
* Fetch type from string.
*
* @param type
* @return
*/
public static Type getType(String type) {
for (Type dbType : Type.values()) {
if (dbType.toString().equalsIgnoreCase(type)) {
return dbType;
}
}
return Type.SQLITE;
}
/*
* Database Settings
*/
public Type database = null;
/*
* Database Connection Settings
*/
private String db;
private String user;
private String pass;
/*
* Database Memory
*/
private Connection connection;
private Statement Stmt;
private PreparedStatement Statement;
private ResultSet ResultSet;
/**
* Create a new instance of the wrapper for usage.
*
* @param database
* @param db
* @param user
* @param pass
*/
public MySQL(Type database, String db, String user, String pass) {
this.database = database;
this.db = db;
this.user = user;
this.pass = pass;
}
/**
* Initialize the wrapper
*
* @return Connection
* @throws ClassNotFoundException
* @throws SQLException
*/
public void initialize() {
try {
this.connection();
} catch (SQLException ex) {
log.severe("[" + this.database.toString() + " Database] Failed to connect: " + ex);
} catch (ClassNotFoundException e) {
log.severe("[" + this.database.toString() + " Database] Connector not found: " + e);
}
}
/**
* Connect to the database, return connection.
*
* @return Connection
* @throws ClassNotFoundException
* @throws SQLException
*/
private Connection connection() throws ClassNotFoundException, SQLException {
if (this.database.equals(database.SQLITE)) {
Class.forName("org.sqlite.JDBC");
this.connection = DriverManager.getConnection(this.db);
} else {
Class.forName("com.mysql.jdbc.Driver");
this.connection = DriverManager.getConnection(this.db, this.user, this.pass);
}
return this.connection;
}
/**
* Check to see if table exists.
*
* @param table
* @return boolean
*/
public boolean checkTable(String table) {
initialize();
try {
DatabaseMetaData dbm = this.connection.getMetaData();
this.ResultSet = dbm.getTables(null, null, table, null);
return this.ResultSet.next();
} catch (SQLException ex) {
log.severe("[" + this.database.toString() + " Database] Table check failed: " + ex);
} finally {
this.close();
}
return false;
}
/**
* Execute pure SQL String.
*
* @param query
* @return
*/
public ResultSet executeQuery(String query) {
initialize();
try {
this.Statement = this.connection.prepareStatement(query);
return this.Statement.executeQuery();
} catch (SQLException ex) {
log.severe("[" + this.database.toString() + " Database] Could not execute query: " + ex);
}
return null;
}
/**
* Execute Query with variables.
*
* @param query
* @param variables
* @return
*/
public ResultSet executeQuery(String query, Object... variables) {
initialize();
try {
this.Statement = this.connection.prepareStatement(query);
int i = 1;
for (Object obj : variables) {
this.Statement.setObject(i, obj);
i++;
}
return this.Statement.executeQuery();
} catch (SQLException ex) {
log.severe("[" + this.database.toString() + " Database] Could not execute query: " + ex);
}
return null;
}
/**
* Execute pure SQL String.
*
* @param query
* @return
*/
public int executeUpdate(String query) {
initialize();
try {
this.Stmt = this.connection.createStatement();
return this.Stmt.executeUpdate(query);
} catch (SQLException ex) {
log.severe("[" + this.database.toString() + " Database] Could not execute query: " + ex);
}
return 0;
}
/**
* Execute Query with variables.
*
* @param query
* @param variables
* @return
*/
public int executeUpdate(String query, Object... variables) {
initialize();
try {
this.Statement = this.connection.prepareStatement(query);
int i = 1;
for (Object obj : variables) {
this.Statement.setObject(i, obj);
i++;
}
return this.Statement.executeUpdate();
} catch (SQLException ex) {
log.severe("[" + this.database.toString() + " Database] Could not execute query: " + ex);
}
return 0;
}
public void close() {
try {
if (this.Statement != null) {
this.Statement.close();
}
if (this.ResultSet != null) {
this.ResultSet.close();
}
if (this.connection != null) {
this.connection.close();
}
} catch (SQLException ex) {
log.severe("[" + this.database.toString() + " Database] Failed to close connection: " + ex);
// Close anyway.
this.connection = null;
this.Statement = null;
this.ResultSet = null;
}
}
protected void finalize() {
close();
}
}

View File

@ -0,0 +1,71 @@
package de.gurkengewuerz.postfix_rest_send.objects;
import de.gurkengewuerz.postfix_rest_send.Main;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by gurkengewuerz.de on 13.07.2017.
*/
public class BruteforceFilter {
private final HashMap<String, Integer> attempts = new HashMap<>();
private int maxAttemps = 3;
public BruteforceFilter(int maxAttemps) {
this.maxAttemps = maxAttemps;
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
refresh();
} catch (SQLException e) {
Logger.getLogger(BruteforceFilter.class.getName()).log(Level.SEVERE, null, e);
}
}
}, 0, 2 * 60 * 1000);
}
public BruteforceFilter() {
this(3);
}
private void refresh() throws SQLException {
ResultSet rs = Main.getDatabase().executeQuery("SELECT ip, COUNT(*) count FROM token_bruteforce WHERE occurred > ? GROUP BY ip ORDER BY COUNT(*) DESC;", (System.currentTimeMillis() / 1000) - (24 * 60 * 60));
synchronized (attempts) {
attempts.clear();
while (rs.next()) {
attempts.put(rs.getString("ip"), rs.getInt("count"));
}
}
if (Main.getConfig().debug())
Logger.getLogger(getClass().getName()).log(Level.INFO, "refreshed bans (" + attempts.size() + ")");
}
public void failed(String ip) {
if (Main.getConfig().getBoolean("disable_bruteforcefilter")) return;
Main.getDatabase().executeUpdate("INSERT INTO token_bruteforce (ip, occurred) VALUES (?, ?);", ip, System.currentTimeMillis() / 1000);
synchronized (attempts) {
if (attempts.containsKey(ip)) {
attempts.replace(ip, attempts.get(ip) + 1);
} else {
attempts.put(ip, 1);
}
if (Main.getConfig().debug())
Logger.getLogger(getClass().getName()).log(Level.INFO, "banned " + ip + " attemp " + attempts.get(ip));
}
}
public boolean banned(String ip) {
if (Main.getConfig().getBoolean("disable_bruteforcefilter")) return false;
synchronized (attempts) {
return attempts.containsKey(ip) && attempts.get(ip) >= maxAttemps;
}
}
}

View File

@ -0,0 +1,11 @@
package de.gurkengewuerz.postfix_rest_send.objects;
public class ReturnHolder {
public final String[] output;
public final String[] error;
public ReturnHolder(String[] output, String[] error) {
this.output = output;
this.error = error;
}
}

View File

@ -0,0 +1,71 @@
package de.gurkengewuerz.postfix_rest_send.utils;
import de.gurkengewuerz.postfix_rest_send.objects.ReturnHolder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by gurkengewuerz.de on 13.07.2017.
*/
public class BashUtils {
public static ReturnHolder run(boolean directPrint, String... command) {
try {
ProcessBuilder pb = new ProcessBuilder(command);
Process p = pb.start();
return getOutput(directPrint, p);
} catch (IOException ex) {
Logger.getLogger(BashUtils.class.getName()).log(Level.SEVERE, "error executing command", ex);
}
return new ReturnHolder(new String[0], new String[]{"exception"});
}
private static ReturnHolder getOutput(boolean print, Process P) {
try {
BufferedReader stdInput = new BufferedReader(new InputStreamReader(P.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(P.getErrorStream()));
ArrayList<String> output = new ArrayList<>();
ArrayList<String> error = new ArrayList<>();
Thread t = null;
if (print) {
t = new Thread(() -> {
String s;
try {
while ((s = stdError.readLine()) != null) {
error.add(s);
System.out.println("ERR: " + s);
}
} catch (IOException ex) {
Logger.getLogger(BashUtils.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
String s;
while ((s = stdInput.readLine()) != null) {
output.add(s);
if (print) {
System.out.println("OUT: " + s);
}
}
if (t != null) {
if (t.isAlive()) {
t.stop();
}
}
while ((s = stdError.readLine()) != null) {
error.add(s);
if (print) {
System.out.println("ERR: " + s);
}
}
return new ReturnHolder(output.toArray(new String[output.size()]), error.toArray(new String[error.size()]));
} catch (IOException ex) {
Logger.getLogger(BashUtils.class.getName()).log(Level.SEVERE, null, ex);
}
return new ReturnHolder(new String[0], new String[]{"exception"});
}
}

View File

@ -0,0 +1,21 @@
package de.gurkengewuerz.postfix_rest_send.utils;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.UUID;
/**
* Created by gurkengewuerz.de on 13.07.2017.
*/
public class RandomUtils {
public static String rndToken() {
return rndToken("");
}
public static String rndToken(String extraSalt) {
String uuidFront = UUID.randomUUID().toString();
String uuidBack = UUID.randomUUID().toString();
String salted = uuidFront + System.currentTimeMillis() + uuidBack + extraSalt;
return DigestUtils.sha256Hex(salted);
}
}