forked from j62/ctbrec
Implemented HMAC authentication in RecorderServlet
This commit is contained in:
parent
8c7385229f
commit
d62bba5599
|
@ -71,7 +71,7 @@ public class Config {
|
||||||
|
|
||||||
public void save() throws IOException {
|
public void save() throws IOException {
|
||||||
Moshi moshi = new Moshi.Builder().build();
|
Moshi moshi = new Moshi.Builder().build();
|
||||||
JsonAdapter<Settings> adapter = moshi.adapter(Settings.class);
|
JsonAdapter<Settings> adapter = moshi.adapter(Settings.class).indent(" ");
|
||||||
String json = adapter.toJson(settings);
|
String json = adapter.toJson(settings);
|
||||||
File configDir = OS.getConfigDir();
|
File configDir = OS.getConfigDir();
|
||||||
File configFile = new File(configDir, filename);
|
File configFile = new File(configDir, filename);
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package ctbrec;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Hmac {
|
||||||
|
|
||||||
|
private static final transient Logger LOG = LoggerFactory.getLogger(Hmac.class);
|
||||||
|
|
||||||
|
public static byte[] generateKey() {
|
||||||
|
LOG.debug("Generating key");
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
byte[] key = new byte[32];
|
||||||
|
random.nextBytes(key);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String calculate(String msg, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException, IllegalStateException, UnsupportedEncodingException {
|
||||||
|
Mac mac = Mac.getInstance("HmacSHA256");
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA256");
|
||||||
|
mac.init(keySpec);
|
||||||
|
byte[] result = mac.doFinal(msg.getBytes("UTF-8"));
|
||||||
|
String hmac = bytesToHex(result);
|
||||||
|
return hmac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean validate(String msg, byte[] key, String hmacToCheck) throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException {
|
||||||
|
return Hmac.calculate(msg, key).equals(hmacToCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte array to a string
|
||||||
|
*
|
||||||
|
* @param hash
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
static String bytesToHex(byte[] hash) {
|
||||||
|
StringBuffer hexString = new StringBuffer();
|
||||||
|
for (int i = 0; i < hash.length; i++) {
|
||||||
|
String hex = Integer.toHexString(0xff & hash[i]);
|
||||||
|
if (hex.length() == 1)
|
||||||
|
hexString.append('0');
|
||||||
|
hexString.append(hex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,4 +16,6 @@ public class Settings {
|
||||||
public String lastDownloadDir = "";
|
public String lastDownloadDir = "";
|
||||||
public List<Model> models = new ArrayList<Model>();
|
public List<Model> models = new ArrayList<Model>();
|
||||||
public boolean determineResolution = false;
|
public boolean determineResolution = false;
|
||||||
|
public boolean requireAuthentication = false;
|
||||||
|
public byte[] key = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,12 @@ package ctbrec.recorder.server;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||||
|
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,6 +24,8 @@ import org.slf4j.LoggerFactory;
|
||||||
import com.squareup.moshi.JsonAdapter;
|
import com.squareup.moshi.JsonAdapter;
|
||||||
import com.squareup.moshi.Moshi;
|
import com.squareup.moshi.Moshi;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.Hmac;
|
||||||
import ctbrec.InstantJsonAdapter;
|
import ctbrec.InstantJsonAdapter;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
@ -43,6 +48,14 @@ public class RecorderServlet extends HttpServlet {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String json = body(req);
|
String json = body(req);
|
||||||
|
boolean isRequestAuthenticated = checkAuthentication(req, json);
|
||||||
|
if(!isRequestAuthenticated) {
|
||||||
|
resp.setStatus(SC_UNAUTHORIZED);
|
||||||
|
String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
|
||||||
|
resp.getWriter().write(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LOG.debug("Request: {}", json);
|
LOG.debug("Request: {}", json);
|
||||||
Moshi moshi = new Moshi.Builder()
|
Moshi moshi = new Moshi.Builder()
|
||||||
.add(Instant.class, new InstantJsonAdapter())
|
.add(Instant.class, new InstantJsonAdapter())
|
||||||
|
@ -116,6 +129,21 @@ public class RecorderServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkAuthentication(HttpServletRequest req, String body) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException {
|
||||||
|
boolean authenticated = false;
|
||||||
|
if(Config.getInstance().getSettings().key != null) {
|
||||||
|
if(req.getHeader("CTBREC-HMAC") == null) {
|
||||||
|
authenticated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] key = Config.getInstance().getSettings().key;
|
||||||
|
authenticated = Hmac.validate(body, key, req.getHeader("CTBREC-HMAC"));
|
||||||
|
} else {
|
||||||
|
authenticated = true;
|
||||||
|
}
|
||||||
|
return authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
private String body(HttpServletRequest req) throws IOException {
|
private String body(HttpServletRequest req) throws IOException {
|
||||||
StringBuilder body = new StringBuilder();
|
StringBuilder body = new StringBuilder();
|
||||||
BufferedReader br = req.getReader();
|
BufferedReader br = req.getReader();
|
||||||
|
|
Loading…
Reference in New Issue