/************************************************************************* * * * EJBCA Community: The OpenSource Certificate Authority * * * * 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.ejbca.ui.web.protocol; import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.ejb.EJB; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.cesecore.authentication.tokens.AlwaysAllowLocalAuthenticationToken; import org.cesecore.authentication.tokens.AuthenticationToken; import org.cesecore.authentication.tokens.UsernamePrincipal; import org.cesecore.authentication.tokens.WebPrincipal; import org.cesecore.configuration.GlobalConfigurationSessionLocal; import org.ejbca.core.model.InternalEjbcaResources; import org.ejbca.core.model.authorization.AccessRulesConstants; import org.ejbca.core.model.era.RaMasterApiProxyBeanLocal; import org.ejbca.core.protocol.NoSuchAliasException; import org.ejbca.ui.web.LimitLengthASN1Reader; import org.ejbca.ui.web.RequestHelper; import org.ejbca.ui.web.pub.ServletUtils; /** * Servlet implementing server side of the Certificate Management Protocols (CMP) * * @version $Id: CmpServlet.java 28713 2018-04-13 14:35:47Z anatom $ */ public class CmpServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger log = Logger.getLogger(CmpServlet.class); private static final InternalEjbcaResources intres = InternalEjbcaResources.getInstance(); /** Only intended to check if Peer connected instance is authorized to CMP at all. */ private final AuthenticationToken raCmpAuthCheckToken = new AlwaysAllowLocalAuthenticationToken(new UsernamePrincipal("cmpProtocolAuthCheck")); private static final String DEFAULT_CMP_ALIAS = "cmp"; @EJB private RaMasterApiProxyBeanLocal raMasterApiProxyBean; @EJB private GlobalConfigurationSessionLocal globalConfigurationSession; /** * Handles HTTP post * * @param request java standard arg * @param response java standard arg * * @throws IOException input/output error */ @Override public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws IOException { if (log.isTraceEnabled()) { log.trace(">doPost()"); } boolean isProtocolAuthorized = raMasterApiProxyBean.isAuthorizedNoLogging(raCmpAuthCheckToken, AccessRulesConstants.REGULAR_PEERPROTOCOL_CMP); try { if (!isProtocolAuthorized) { log.info("CMP Protocol not authorized for this Peer"); response.sendError(HttpServletResponse.SC_FORBIDDEN, "CMP Protocol not authorized for this Peer"); return; } final String alias = getAlias(request.getPathInfo()); if(alias.length() > 32) { log.info("Unaccepted alias more than 32 characters."); response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unaccepted alias more than 32 characters."); return; } final ServletInputStream sin = request.getInputStream(); // This small code snippet is inspired/copied by apache IO utils to Tomas Gustavsson... final ByteArrayOutputStream output = new ByteArrayOutputStream(); final byte[] buf = new byte[1024]; int n = 0; int bytesRead = 0; while (-1 != (n = sin.read(buf))) { bytesRead += n; if (bytesRead > LimitLengthASN1Reader.MAX_REQUEST_SIZE) { throw new IllegalArgumentException("Request is larger than "+LimitLengthASN1Reader.MAX_REQUEST_SIZE+" bytes."); } output.write(buf, 0, n); } service(output.toByteArray(), request.getRemoteAddr(), response, alias); } catch (IOException | RuntimeException e) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); log.info(intres.getLocalizedMessage("cmp.errornoasn1"), e); } if (log.isTraceEnabled()) { log.trace("doGet()"); } log.info("Received un-allowed method GET in CMP servlet: query string=" + request.getQueryString()); response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "You can only use POST!"); if (log.isTraceEnabled()) { log.trace("". We extract the "SOME IDENTIFYING // TEXT" and that will be the CMP configuration alias. final String alias; if (pathInfo!=null && pathInfo.length()>1) { alias = pathInfo.substring(1); if (log.isDebugEnabled()) { log.debug("Using CMP configuration alias: " + alias); } } else { alias = DEFAULT_CMP_ALIAS; if (log.isDebugEnabled()) { log.debug("No CMP alias specified in the URL. Using the default alias: " + DEFAULT_CMP_ALIAS); } } return alias; } }