/************************************************************************* * * * SignServer: The OpenSource Automated Signing Server * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or any later version. * * * * See terms of license at gnu.org. * * * *************************************************************************/ package org.signserver.web; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.*; import javax.ejb.EJB; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.log4j.Logger; import org.bouncycastle.util.encoders.Base64; import org.signserver.common.*; import org.signserver.ejb.interfaces.IWorkerSession; import org.signserver.server.CertificateClientCredential; import org.signserver.server.IClientCredential; import org.signserver.server.UsernamePasswordClientCredential; import org.signserver.server.log.AdminInfo; import org.signserver.server.log.IWorkerLogger; import org.signserver.server.log.LogMap; /** * GenericProcessServlet is a general Servlet passing on it's request info to the worker configured by either * workerId or workerName parameters. * * It will create a GenericServletRequest that is sent to the worker and expects a GenericServletResponse * sent back to the client. * * @author Philip Vendil * @author Markus KilÄs * @version $Id: GenericProcessServlet.java 3441 2013-04-17 07:42:13Z malu9369 $ */ public class GenericProcessServlet extends HttpServlet { /** Logger for this class. */ private static final Logger LOG = Logger.getLogger( GenericProcessServlet.class); private static final long serialVersionUID = 1L; private static final String FORM_URL_ENCODED = "application/x-www-form-urlencoded"; private static final String METHOD_GET = "GET"; private static final String WORKERID_PROPERTY_NAME = "workerId"; private static final String WORKERNAME_PROPERTY_NAME = "workerName"; private static final String WORKERNAME_PROPERTY_OVERRIDE = "workerNameOverride"; private static final String DATA_PROPERTY_NAME = "data"; private static final String ENCODING_PROPERTY_NAME = "encoding"; private static final String ENCODING_BASE64 = "base64"; private static final long MAX_UPLOAD_SIZE = 100 * 1024 * 1024; // 100MB (100*1024*1024); private static final String HTTP_AUTH_BASIC_AUTHORIZATION = "Authorization"; private static final String HTTP_AUTH_BASIC_WWW_AUTHENTICATE = "WWW-Authenticate"; private static final String PDFPASSWORD_PROPERTY_NAME = "pdfPassword"; private final Random random = new Random(); @EJB private IWorkerSession.ILocal workersession; private IWorkerSession.ILocal getWorkerSession() { if (workersession == null) { try { Context context = new InitialContext(); workersession = (org.signserver.ejb.interfaces.IWorkerSession.ILocal) context.lookup(IWorkerSession.ILocal.JNDI_NAME); } catch (NamingException e) { LOG.error(e); } } return workersession; } /** * Handles http post. * * @param req servlet request * @param res servlet response * * @throws IOException input/output error * @throws ServletException error */ @Override public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { LOG.debug(">doPost()"); int workerId = 1; byte[] data = null; String fileName = null; String pdfPassword = null; boolean workerRequest = false; if (LOG.isDebugEnabled()) { LOG.debug("Received a request with length: " + req.getContentLength()); } final String workerNameOverride = (String) req.getAttribute(WORKERNAME_PROPERTY_OVERRIDE); if (workerNameOverride != null) { workerId = getWorkerSession().getWorkerId(workerNameOverride); workerRequest = true; } //String username = req.getParameter("username"); //String password = req.getParameter("password"); //System.out.println("User: "+username); //System.out.println("Pass: "+password); //System.out.println("2"); if (ServletFileUpload.isMultipartContent(req)) { final FileItemFactory factory = new DiskFileItemFactory(); final ServletFileUpload upload = new ServletFileUpload(factory); // Limit the maximum size of input upload.setSizeMax(MAX_UPLOAD_SIZE); try { final List items = upload.parseRequest(req); final Iterator iter = items.iterator(); FileItem fileItem = null; while (iter.hasNext()) { final Object o = iter.next(); if (o instanceof FileItem) { final FileItem item = (FileItem) o; if (item.isFormField()) { if (!workerRequest) { if (WORKERNAME_PROPERTY_NAME.equals(item.getFieldName())) { if (LOG.isDebugEnabled()) { LOG.debug("Found a signerName in the request: " + item.getString()); } workerId = getWorkerSession().getWorkerId(item.getString()); } else if (WORKERID_PROPERTY_NAME.equals(item.getFieldName())) { if (LOG.isDebugEnabled()) { LOG.debug("Found a signerId in the request: " + item.getString()); } try { workerId = Integer.parseInt(item.getString()); } catch (NumberFormatException ignored) { } } } if (PDFPASSWORD_PROPERTY_NAME.equals(item.getFieldName())) { if (LOG.isDebugEnabled()) { LOG.debug("Found a pdfPassword in the request."); } pdfPassword = item.getString("ISO-8859-1"); } } else { // We only care for one upload at a time right now if (fileItem == null) { fileItem = item; } } } } if (fileItem == null) { sendBadRequest(res, "Missing file content in upload"); return; } else { fileName = fileItem.getName(); data = fileItem.get(); } } catch (FileUploadException ex) { throw new ServletException("Upload failed", ex); } } else { if (!workerRequest) { String name = req.getParameter(WORKERNAME_PROPERTY_NAME); if (name != null) { if (LOG.isDebugEnabled()) { LOG.debug("Found a signerName in the request: " + name); } workerId = getWorkerSession().getWorkerId(name); } String id = req.getParameter(WORKERID_PROPERTY_NAME); if (id != null) { if (LOG.isDebugEnabled()) { LOG.debug("Found a signerId in the request: " + id); } workerId = Integer.parseInt(id); } } if (req.getParameter(PDFPASSWORD_PROPERTY_NAME) != null) { pdfPassword = req.getParameter(PDFPASSWORD_PROPERTY_NAME); if (LOG.isDebugEnabled()) { LOG.debug("Found a pdfPassword in the request."); } } if (METHOD_GET.equalsIgnoreCase(req.getMethod()) || (req.getContentType() != null && req.getContentType().contains(FORM_URL_ENCODED))) { LOG.debug("Request is FORM_URL_ENCODED"); if (req.getParameter(DATA_PROPERTY_NAME) == null) { sendBadRequest(res, "Missing field 'data' in request"); return; } data = req.getParameter(DATA_PROPERTY_NAME).getBytes(); String encoding = req.getParameter(ENCODING_PROPERTY_NAME); if (encoding != null && !encoding.isEmpty()) { if (ENCODING_BASE64.equalsIgnoreCase(encoding)) { LOG.info("Decoding base64 data"); data = Base64.decode(data); } else { sendBadRequest(res, "Unknown encoding for the 'data' field: " + encoding); return; } } } else { // Pass-through the content to be handled by worker if // unknown content-type if (LOG.isDebugEnabled()) { LOG.debug("Request Content-type: " + req.getContentType()); } // Get an input stream and read the bytes from the stream InputStream in = req.getInputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream(); int len; byte[] buf = new byte[1024]; while ((len = in.read(buf)) > 0) { os.write(buf, 0, len); } in.close(); os.close(); data = os.toByteArray(); } } // Limit the maximum size of input if (data.length > MAX_UPLOAD_SIZE) { LOG.error("Content length exceeds 100MB, not processed: " + req.getContentLength()); res.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, "Maximum content length is 100 MB"); } else { processRequest(req, res, workerId, data, fileName, pdfPassword); } LOG.debug("doGet()"); doPost(req, res); LOG.debug("