package servlets.hstsSuperCookie;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class HSTSServlet
*/
public class HstsSuperCookieExistingIDServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Pattern pathRegexPattern;
private static final int ID_IMAGE_WIDTH_PER_CHAR = 19;
private static final int ID_IMAGE_HEIGHT = 30;
private static final int ID_IMAGE_FONT_SIZE = 30;
private static final int ID_IMAGE_TEXT_X_POSITION = 0;
private static final int ID_IMAGE_TEXT_Y_POSITION = ID_IMAGE_HEIGHT - 5;
/**
* @see HttpServlet#HttpServlet()
*/
public HstsSuperCookieExistingIDServlet() {
super();
this.pathRegexPattern = Pattern.compile("^/hstsSuperCookie/existingID/([10]{" + (HstsSuperCookieStartServlet.ID_LENGTH - 1) + "})$");
}
/**
* Serves requests for hsts[1 to ID_LENGTH].browserprint.info/hstsSuperCookie/existingID/*
* This script extracts the ID from the client one bit at a time.
*
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int extractedBit;
if(request.getServerPort() == 80){
extractedBit = 0;
}
else if(request.getServerPort() == 443){
extractedBit = 1;
}
else{
System.err.println("HstsSuperCookieExistingIDServlet: Unexpected protocol.");
response.sendError(404);
return;
}
int subdomainNumber;
{
String subdomain = request.getServerName();
Matcher domainRegexMatcher = Pattern.compile("^hsts(\\d+)\\..*$").matcher(subdomain);
if(domainRegexMatcher.matches() == false){
System.err.println("HstsSuperCookieExistingIDServlet: Invalid subdomain <" + subdomain + ">.");
response.sendError(404);
return;
}
subdomainNumber = Integer.parseInt(domainRegexMatcher.group(1));
}
int subdomainGroupIndex = (subdomainNumber - 1) % HstsSuperCookieStartServlet.ID_LENGTH + 1;//1 = 1; 2 = 2; 3 = 3; 4 = 4; 5 = 1
if(subdomainGroupIndex < HstsSuperCookieStartServlet.ID_LENGTH){
//Redirect the client to the next subdomain in the chain.
response.sendRedirect("http://hsts" + (subdomainNumber + 1) + "." + getServletContext().getInitParameter("websiteBaseURL") + request.getRequestURI() + extractedBit);
}
else{//Must be == ID_LENGTH
//This is the last subdomain in the ID extraction chain.
//First, get the full ID.
Matcher pathRegexMatcher = pathRegexPattern.matcher(request.getRequestURI());
if(pathRegexMatcher.matches() == false){
System.err.println("HstsSuperCookieExistingIDServlet: Invalid path. Must contain valid ID of length " + HstsSuperCookieStartServlet.ID_LENGTH + ". Path = <" + request.getRequestURI() + ">.");
response.sendError(404);
return;
}
String id = pathRegexMatcher.group(1) + extractedBit;
//Output the ID.
if(id.length() % 4 == 0){
//We've got a multiple of 4 bits so we can convert the ID bit string to something more compact, a hex.
id = Integer.toHexString(Integer.parseInt(id, 2));
}
int image_width = id.length() * ID_IMAGE_WIDTH_PER_CHAR;
BufferedImage bImage = new BufferedImage(image_width, ID_IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bImage.createGraphics();
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, image_width, ID_IMAGE_HEIGHT);
g2d.setColor(Color.black);
g2d.setFont(new Font("Liberation Mono", Font.PLAIN, ID_IMAGE_FONT_SIZE));
g2d.drawString(id, ID_IMAGE_TEXT_X_POSITION, ID_IMAGE_TEXT_Y_POSITION);
response.setContentType("image/png");
ImageIO.write(bImage, "png", response.getOutputStream());
//response.sendRedirect("http://dummyimage.com/50x30/fff/000&text=" + id);
return;
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}