john pfeiffer
  • Home
  • Categories
  • Tags
  • Archives

UploadSSL

// 2012-07-08 johnpfeiffer requires Password, SSLCertificate, SSLKey, SSLUtility
// TODO: REFACTOR saveSSLInput( HttpServletRequest request , PrintWriter out )
// TODO: Unit Tests

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class UploadSSL extends HttpServlet
{
    private static final long serialVersionUID = 1L;
    private static final String CLASSVERSION = "0.54";

    private static final String PARAMLOGINUSERPASSWORD = "userPassword";
    private static final String PARAMLOGINBUTTON = "login";
    private static final String PARAMLOGOUTBUTTON = "logout";
    private static final String FORMSTYLE = "style ='margin: 0px; padding: 0px;'";
    private static final String LOGOUTFORMSTYLE = "style ='margin: 0px; padding: 0px;'";

    private static String SSLLOCATION = "/var/lib/ssl/";
    private static String SSLKEYFILENAME = "cert.key";
    private static String SSLCERTIFICATEFILENAME = "cert.crt";
    private static String SSLINTERMEDIATEFILENAME = "intermediate.crt";

    Password loginPassword = null;
    private static String servletURL;
    private ArrayList <String> authorizedTokens;

    public void init( ServletConfig config ) throws ServletException
    {
        super.init( config );
        authorizedTokens = new ArrayList <String>();
        writeToLog( "UploadSSL version " + CLASSVERSION );
        loginPassword = new Password( 8 );
        writeToLog( "One time use login password: " + loginPassword.get() );
    }

    protected void doGet( HttpServletRequest request , HttpServletResponse response ) throws ServletException , IOException
    {
        String contextPath = request.getContextPath();
        String servletName = getServletName();
        servletURL = contextPath + "/" + servletName;
        String sessionToken;

        response.setContentType( "text/html" ); // MIME type
        PrintWriter servletresponse = null;
        try
        {
            servletresponse = response.getWriter();
        }catch( Exception e )
        {
            System.err.println( "Unable to create a PrintWriter" );
            e.printStackTrace();
            System.exit( 1 );
        }

        HttpSession session = request.getSession( true );
        servletresponse.println( getXHTMLHeader( "UploadSSL" ) );
        servletresponse.println( "<body>" );
        String currentToken = "";
        if( session != null )
        {
            currentToken = (String) session.getAttribute( "sessionToken" );
        }

        String logout = request.getParameter( PARAMLOGOUTBUTTON );
        if( logout != null && !logout.isEmpty() && logout.equals( PARAMLOGOUTBUTTON ) )
        {
            logout = "";
            writeToLog( logoutCurrentUser( request , session , currentToken ) );
        }

        if( !authorizedTokens.contains( currentToken ) ) // validate start a session, accidentally keeping an extra token from login?
        {
            String userPassword = request.getParameter( PARAMLOGINUSERPASSWORD );
            if( loginPassword.isValid( userPassword ) )
            {
                userPassword = ""; // use the session, not the password
                session.setMaxInactiveInterval( 5 * 60 ); // 5 * 60 seconds = 5 minutes
                sessionToken = UUID.randomUUID().toString(); // SecureRandom based
                session.setAttribute( "sessionToken" , sessionToken );
                authorizedTokens.add( sessionToken );

                session = changeSessionIdentifier( request ); // security measure against session hijacking
                currentToken = (String) session.getAttribute( "sessionToken" );
                writeToLog( getUTCTimestamp() + " UTC Login successful: " + session.getId() + " , " + currentToken );
                loginPassword = new Password( 8 );
                writeToLog( "One time use login password: " + loginPassword.get() );
            }else
            {
                servletresponse.println( getLoginForm() );
            }
        }

        if( authorizedTokens.contains( currentToken ) ) // resume a session
        {
            // BEGIN APPLICATION SPECIFIC LOGIC HERE
            displayInputForm( request , servletresponse );
            String saving = request.getParameter( "input" );
            if( saving != null && !saving.isEmpty() && saving.equals( "save" ) )
            {
                saveSSLInput( request , servletresponse );
                displaySSLStatus( servletresponse );
                servletresponse.println( "<br /> <br />" + getUTCTimestamp() + " UTC Settings saved <br />" );
                System.out.println( getUTCTimestamp() + " UTC Configuration saved" ); // tomcat6 writes to catalina.out
            }
            // END APPLICATION SPECIFIC LOGIC

            servletresponse.println( "<br />" );
            servletresponse.println( getLogoutForm() );
        }
        servletresponse.println( "</body></html>" );
        servletresponse.close();

    } // end doGet()

    // BEGIN APPLICATION SPECIFIC METHODS

    // this method is ugly =( , needs refactoring
    private void saveSSLInput( HttpServletRequest request , PrintWriter out )
    {
        String userInput = request.getParameter( "userinput" ); // defined in displayInputForm
        String targetFile = request.getParameter( "targetfile" ); // defined in displayInputForm

        if( userInput != null && !userInput.isEmpty() && targetFile != null && !targetFile.isEmpty() )
        {
            if( targetFile.equals( "write-cert.crt" ) || targetFile.equals( "write-intermediate.crt" ) || targetFile.equals( "write-cert.key" ) )
            {
                out.println( "<pre>" + targetFile + "</pre> " );
                out.println( "<pre>" + userInput + "</pre> " );
            }
        }

        if( targetFile.equals( "write-cert.crt" ) )
        {
            SSLCertificate cert = new SSLCertificate( userInput );
            if( cert.isValid() )
            {
                try
                {
                    cert.writeToFile( SSLLOCATION + SSLCERTIFICATEFILENAME );
                }catch( IOException ioe )
                {
                    out.println( ioe.getMessage() + "<br />" );
                    System.out.println( ioe.getMessage() );
                }
            }else
            {
                out.println( "ERROR: Input is not a valid PEM format SSL certificate" );
                System.out.println( "ERROR: Input is not a valid PEM format SSL certificate" );
            }
        }else if( targetFile.equals( "write-intermediate.crt" ) )
        {
            SSLCertificate intermediate = new SSLCertificate( userInput );
            if( intermediate.isValid() )
            {
                try
                {
                    intermediate.writeToFile( SSLLOCATION + SSLINTERMEDIATEFILENAME );
                }catch( IOException ioe )
                {
                    out.println( ioe.getMessage() + "<br />" );
                    System.out.println( ioe.getMessage() );
                }
            }else
            {
                out.println( "ERROR: Input is not a valid PEM format SSL certificate" );
                System.out.println( "ERROR: Input is not a valid PEM format SSL certificate" );
            }
        }else if( targetFile.equals( "write-cert.key" ) )
        {
            SSLKey sslkey = new SSLKey( userInput );
            try
            {
                sslkey.writeToFile( SSLLOCATION + SSLKEYFILENAME );
            }catch( IOException ioe )
            {
                out.println( ioe.getMessage() + "<br />" );
                System.out.println( ioe.getMessage() );
            }
        }else
        {
            out.println( "Error: invalid option selected" );
        }

        targetFile = null;
    }

    private void displaySSLStatus( PrintWriter out )
    {
        try
        {
            SSLUtility openssl = new SSLUtility();
            if( openssl.isCertificateAndKeyValid( SSLLOCATION + SSLCERTIFICATEFILENAME , SSLLOCATION + SSLKEYFILENAME ) )
            {
                out.println( "SUCCESS: Current SSL Certificate and Key match <br />" );
            }else
            {
                out.println( "ERROR: Current SSL Certificate and Key do not match <br />" );
            }
            out.println( "Certificate and Intermediate Check Result... <br />" );
            String intermediateCheckResult = openssl.isCertificateAndIntermediateValid( SSLLOCATION + SSLCERTIFICATEFILENAME , SSLLOCATION + SSLINTERMEDIATEFILENAME );
            out.println( intermediateCheckResult );
        }catch( IOException ioe )
        {
            out.println( ioe.getMessage() );
        }
    }

    private void displayInputForm( HttpServletRequest request , PrintWriter out )
    {
        String contextPath = request.getContextPath();
        String servletName = getServletName();
        String submitTarget = contextPath + "/" + servletName;
        out.println( "<br />" );
        out.println( "<form id='upload' action='" + submitTarget + "' method=\"post\" >" );
        out.println( "<label><input type='radio' name='targetfile' value='write-cert.crt' /> Upload cert.crt </label>" );
        out.println( "<label><input type='radio' name='targetfile' value='write-intermediate.crt' /> Upload intermediate.crt </label>" );
        out.println( "<label><input type='radio' name='targetfile' value='write-cert.key' /> Upload cert.key </label>" );
        out.println( "<br /><br />" );
        out.println( "<textarea name='userinput' rows='10' cols='80'>Delete this and Paste your SSL Certificate or SSL Key</textarea>" );
        out.println( "<br /><br />" );
        out.println( "<div><input type='submit' name='input' value='save'/></div>" );
        out.println( "</form>" );
        out.println( "<script type='text/javascript'> document.forms[ 'upload' ].elements[ 'userinput' ].focus(); </script>" );
    }

    // END APPLICATION SPECIFIC METHODS

    // GENERIC HELPER METHODS
    private HttpSession changeSessionIdentifier( HttpServletRequest request )
    {
        HttpSession session = request.getSession();
        HashMap <String , Object> attributes = new HashMap <String , Object>();
        @SuppressWarnings( "unchecked" )
        Enumeration <String> attributeNames = (Enumeration <String>) session.getAttributeNames();
        while( attributeNames != null && attributeNames.hasMoreElements() )
        {
            String name = attributeNames.nextElement();
            Object value = session.getAttribute( name );
            attributes.put( name , value );
        }
        session.invalidate();
        HttpSession newSession = request.getSession();
        Set <Map.Entry <String , Object>> attributeValues = attributes.entrySet();
        Iterator <Map.Entry <String , Object>> it = attributeValues.iterator(); // copy back the session content
        while( it.hasNext() )
        {
            Map.Entry <String , Object> entry = it.next();
            newSession.setAttribute( (String) entry.getKey() , entry.getValue() );
        }
        return newSession;
    }

    private String getUTCTimestamp()
    {
        long currentTimeMilliseconds = System.currentTimeMillis();
        Date now = new Date( currentTimeMilliseconds );
        SimpleDateFormat utcFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
        utcFormat.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
        return utcFormat.format( now );
    }

    private void writeToLog( String content )
    {
        System.out.println( content ); // tomcat defaults to catalina.out
    }

    // side effect to the session?
    private String logoutCurrentUser( HttpServletRequest request , HttpSession session , String currentToken )
    {
        StringBuilder strb = new StringBuilder();
        if( session != null )
        {
            while( authorizedTokens.contains( currentToken ) )
            {
                authorizedTokens.remove( currentToken );
            }
            if( request.isRequestedSessionIdValid() == true )
            {
                strb.append( getUTCTimestamp() + " UTC " + session.getId() + " , " + currentToken + " Logged out." );
                session.invalidate();
            }else
            {
                strb.append( "Logged out.  Session is invalidated." );
            }
        }
        return strb.toString();
    }

    private static String getLogoutForm()
    {
        StringBuilder strb = new StringBuilder();
        String newline = System.getProperty( "line.separator" );
        strb.append( "<form " + LOGOUTFORMSTYLE + " id='" + PARAMLOGOUTBUTTON + "' action='" + servletURL + "' method='post' >" + newline );
        strb.append( "<div><input type='submit' name='" + PARAMLOGOUTBUTTON + "' value='" + PARAMLOGOUTBUTTON + "' /></div>" + newline );
        strb.append( "</form>" + newline );
        return strb.toString();
    }

    private static String getLoginForm()
    {
        StringBuilder strb = new StringBuilder();
        String newline = System.getProperty( "line.separator" );
        strb.append( "<form " + FORMSTYLE + " id='" + PARAMLOGINBUTTON + "' action='" + servletURL + "' method='post' >" + newline );
        strb.append( "Password: &nbsp; <input type='password' name='" + PARAMLOGINUSERPASSWORD + "' id='" + PARAMLOGINUSERPASSWORD + "' /> <br /><br />" + newline );
        strb.append( "<span><input type='submit' name='" + PARAMLOGINBUTTON + "' value='" + PARAMLOGINBUTTON + "'/></span>" + newline );
        strb.append( "</form>" + newline );
        // strb.append( "<script type='text/javascript'> document.forms[ '"+ PARAMLOGINBUTTON + "' ].elements[ '" + PARAMLOGINUSERPASSWORD +
        // "' ].focus(); </script>" + newline );
        strb.append( "<script type='text/javascript'> document.getElementById( '" + PARAMLOGINUSERPASSWORD + "' ).focus(); </script>" );
        return strb.toString();
    }

    private static String getXHTMLHeader( String title )
    {
        StringBuilder strb = new StringBuilder();
        String newline = System.getProperty( "line.separator" );
        strb.append( "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" + newline );
        strb.append( "<html xmlns=\"http://www.w3.org/1999/xhtml\">" + newline );
        strb.append( "<head><title>" + title + "</title>" + newline );
        strb.append( "<meta http-equiv='Content-Type' content='text/html;charset=utf-8' />" + newline );
        strb.append( "<link type='text/css' rel='stylesheet' href='css/style.css' />" + newline );
        // strb.append( "<script type='text/javascript' src='" + contextPath +
        // "/javascript.js'></script> + newline " );
        strb.append( "</head>" + newline );
        return strb.toString();
    }

    protected void doPost( HttpServletRequest request , HttpServletResponse response ) throws ServletException , IOException
    {
        doGet( request , response );
    }
} // end class

  • « SSLUtility
  • Haproxy load balancing http https »

Published

Jul 9, 2012

Category

java-servlet

~1047 words

Tags

  • java-servlet 61
  • uploadssl 1