Package org.ejbca.ui.web.pub

Source Code of org.ejbca.ui.web.pub.AutoEnrollServlet

/*************************************************************************
*                                                                       *
*  EJBCA: 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.pub;

import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;

import javax.ejb.EJB;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.cesecore.core.ejb.ca.store.CertificateProfileSessionLocal;
import org.cesecore.core.ejb.ra.raadmin.EndEntityProfileSessionLocal;
import org.ejbca.config.GlobalConfiguration;
import org.ejbca.core.ejb.ca.sign.SignSessionLocal;
import org.ejbca.core.ejb.ca.store.CertificateStoreSessionLocal;
import org.ejbca.core.ejb.config.GlobalConfigurationSessionLocal;
import org.ejbca.core.ejb.ra.UserAdminSessionLocal;
import org.ejbca.core.ejb.ra.raadmin.RaAdminSessionLocal;
import org.ejbca.core.model.SecConst;
import org.ejbca.core.model.log.Admin;
import org.ejbca.core.model.ra.UserDataConstants;
import org.ejbca.core.model.ra.UserDataVO;
import org.ejbca.core.protocol.IResponseMessage;
import org.ejbca.core.protocol.MSPKCS10RequestMessage;
import org.ejbca.core.protocol.X509ResponseMessage;
import org.ejbca.ui.web.RequestHelper;
import org.ejbca.util.ActiveDirectoryTools;
import org.ejbca.util.Base64;
import org.ejbca.util.CertTools;
import org.ejbca.util.CryptoProviderTools;
import org.ejbca.util.StringTools;
import org.ejbca.util.dn.DnComponents;
import org.ejbca.util.passgen.PasswordGeneratorFactory;

/**
* Parses a posted request and returns a correct certificate depending on the type.
*
* This Servlet assumes that it is protected by an Kerberos verifying proxy and is insecure to use without.
*
* @version $Id: AutoEnrollServlet.java 11634 2011-03-30 09:49:31Z jeklund $
*/
public class AutoEnrollServlet extends HttpServlet {

  private static final long serialVersionUID = 1L;
  private final static Logger log = Logger.getLogger(AutoEnrollServlet.class);

  @EJB
  private CertificateStoreSessionLocal certificateStoreSession;
  @EJB
  private EndEntityProfileSessionLocal endEntityProfileSession;
  @EJB
  private RaAdminSessionLocal raAdminSession;
  @EJB
  private SignSessionLocal signSession;
  @EJB
  private UserAdminSessionLocal userAdminSession;
  @EJB
  private CertificateProfileSessionLocal certificateProfileSession;
  @EJB
  private GlobalConfigurationSessionLocal globalConfigurationSession;
 
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    try {
      // Install BouncyCastle provider
      CryptoProviderTools.installBCProvider();
    } catch (Exception e) {
      throw new ServletException(e);
    }
  }

  /**
   * Recievies the request.
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    log.trace(">doPost");
    Admin internalAdmin = Admin.getInternalAdmin();
    GlobalConfiguration globalConfiguration = globalConfigurationSession.getCachedGlobalConfiguration(internalAdmin);
    // Make sure we allow use of this Servlet
    if ( !globalConfiguration.getAutoEnrollUse() ) {
      log.info("Unauthorized access attempt from " + request.getRemoteAddr());
      response.getOutputStream().println("Not allowed.");
      return;
    }
    int caid = globalConfiguration.getAutoEnrollCA();
    if (caid == GlobalConfiguration.AUTOENROLL_DEFAULT_CA) {
      log.info("Configure a proper CA to use with enroll.");
      response.getOutputStream().println("Configure a proper CA to use with enroll.");
      return;
    }
    boolean debugRequest = "true".equalsIgnoreCase(request.getParameter("debug"));
    String debugInfo = "";

    Admin admin = new Admin(Admin.TYPE_RA_USER, request.getRemoteAddr());
    RequestHelper.setDefaultCharacterEncoding(request);

    if (debugRequest) {
      debugInfo += "getAttributeNames:\n";
      Enumeration enumeration = request.getAttributeNames();
      while (enumeration.hasMoreElements()) {
        String temp = enumeration.nextElement().toString();
        debugInfo += temp + " = " + request.getAttribute(temp) + "\n";
      }
      debugInfo += "\ngetParameterNames:\n";
      enumeration = request.getParameterNames();
      while (enumeration.hasMoreElements()) {
        String temp = enumeration.nextElement().toString();
        debugInfo += temp + " = " + request.getParameter(temp) + "\n";
      }
      debugInfo += "\ngetHeaderNames:\n";
      enumeration = request.getHeaderNames();
      while (enumeration.hasMoreElements()) {
        String temp = enumeration.nextElement().toString();
        debugInfo += temp + " = " + request.getHeader(temp) + "\n";
      }
      debugInfo += "Remote address: " + request.getRemoteAddr() + "\n";
      log.info(debugInfo);
    }

    byte[] result = null
    String requestData = MSCertTools.extractRequestFromRawData(request.getParameter("request"));
    if (requestData == null) {
      response.getOutputStream().println("No request supplied..");
      return;
    }
    log.info("Got request: "+requestData);
    // The next line expects apache to forward the kerberos-authenticated user as X-Remote-User"
    String remoteUser = request.getHeader("X-Remote-User") ;
    String usernameShort = StringTools.strip(remoteUser.substring(0, remoteUser.indexOf("@"))).replaceAll("/", "");
    if (remoteUser == null || "".equals(remoteUser) || "(null)".equals(remoteUser)) {
      response.getOutputStream().println("X-Remote-User was not supplied..");
      return;
    }
    MSPKCS10RequestMessage req = null;
    String certificateTemplate = null;
    String command = request.getParameter("command");
    if (command != null && "status".equalsIgnoreCase(command)) {
      response.getOutputStream().println(returnStatus(internalAdmin, "Autoenrolled-" + usernameShort + "-" + request.getParameter("template")));
      return;
    } else {
      // Default command "request"
    }
    req = new MSPKCS10RequestMessage(Base64.decode(requestData.getBytes()));
    certificateTemplate = req.getMSRequestInfoTemplateName();
    int templateIndex = MSCertTools.getTemplateIndex(certificateTemplate);
    /* TODO: Lookup requesting entity in AD here to verify that only Machines request Machine Certificates etc.. Also check permissions
            like who is allowed to enroll for what if possible. */
    // Create or edit a user "Autoenrolled-Username-Templatename"
    String username = "Autoenrolled-" + usernameShort + "-" + certificateTemplate;
    log.info("Got autoenroll request from " + remoteUser + " (" + username + ") for a " + certificateTemplate + "-certificate.");
    String fetchedSubjectDN = null;
    if (MSCertTools.isRequired(templateIndex, MSCertTools.GET_SUBJECTDN_FROM_AD, 0)) {
      fetchedSubjectDN = ActiveDirectoryTools.getUserDNFromActiveDirectory(globalConfiguration, usernameShort);
    }
    int certProfileId = MSCertTools.getOrCreateCertificateProfile(admin, templateIndex, certificateProfileSession);
        int endEntityProfileId = MSCertTools.getOrCreateEndEndtityProfile(admin, templateIndex, certProfileId, caid, usernameShort, fetchedSubjectDN,
                raAdminSession, endEntityProfileSession);
    if (endEntityProfileId == -1) {
      String msg = "Could not retrieve required information from AD.";
      log.error(msg);
      response.getOutputStream().println(msg);
      return;
    }
    // Create user
   
    // The CA needs to use non-LDAP order and we need to have the SAN like "CN=Users, CN=Username, DC=com, DC=company".. why??
    // TODO: fix this here.. or is this an general order issue?
    String subjectDN = fetchedSubjectDN;
    if (subjectDN == null) {
      if (MSCertTools.isRequired(templateIndex, DnComponents.COMMONNAME, 0)) {
        subjectDN = "CN="+usernameShort;
      }
    }
    String subjectAN = "";
    if (MSCertTools.isRequired(templateIndex, DnComponents.UPN, 0)) {
      subjectAN += (subjectAN.length() == 0 ? "" : ",") + "UPN=" +remoteUser;
    }
    if (MSCertTools.isRequired(templateIndex, DnComponents.GUID, 0)) {
      String reqGUID = req.getMSRequestInfoSubjectAltnames()[0];
      subjectAN += (subjectAN.length() == 0 ? "" : ",") + "GUID=" +reqGUID;
    }
    if (MSCertTools.isRequired(templateIndex, DnComponents.DNSNAME, 0)) {
      String reqDNS = req.getMSRequestInfoSubjectAltnames()[1];
      subjectAN += (subjectAN.length() == 0 ? "" : ",") + "DNSNAME=" +reqDNS;
    }
    log.info("sdn=" + subjectDN + ", san=" + subjectAN);
    debugInfo += "\nsdn=" + subjectDN + ", san=" + subjectAN + "\n";
    UserDataVO userData = new UserDataVO(username, subjectDN, caid, subjectAN, null, UserDataConstants.STATUS_NEW, 1,endEntityProfileId, certProfileId,
        new Date(), new Date(), SecConst.TOKEN_SOFT_BROWSERGEN, 0, null);
    String password = PasswordGeneratorFactory.getInstance(PasswordGeneratorFactory.PASSWORDTYPE_LETTERSANDDIGITS).getNewPassword(8,8);
    userData.setPassword(password);
    try {
      if (userAdminSession.existsUser(admin, username)) {
        userAdminSession.changeUser(admin, userData, true);
      } else {
        userAdminSession.addUser(admin, userData, true);
      }
    } catch (Exception e) {
      log.error("Could not add user "+username, e);
    }
    Certificate cert=null;
    debugInfo += "Request: " + requestData + "\n";
    req.setUsername(username);
    req.setPassword(password);
    IResponseMessage resp;
    try {
      resp = signSession.createCertificate(admin, req, X509ResponseMessage.class, null);
      cert = CertTools.getCertfromByteArray(resp.getResponseMessage());
      result = signSession.createPKCS7(admin, cert, true);
      debugInfo += "Resulting cert: " + new String(Base64.encode(result, true)) + "\n";
    } catch (Exception e) {
      log.error("Noooo!!! ", e);
      response.getOutputStream().println("An error has occurred.");
      return;
    }
    if (debugRequest) {
      response.getOutputStream().println(debugInfo);
    } else {
      // Output the certificate
      ServletOutputStream os = response.getOutputStream();
      os.print(RequestHelper.BEGIN_PKCS7_WITH_NL);
      os.print(new String(Base64.encode(result, true)));
      os.print(RequestHelper.END_PKCS7_WITH_NL);
      response.flushBuffer();
      log.info("Sent cert to client");
    }
    log.trace("<doPost");
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    log.trace(">doGet");
    doPost(request, response);
    log.trace("<doGet");
  }

  /**
   * Return "OK" if renewal isn't needed.
   */
  private String returnStatus(Admin admin, String username) {
    if (!userAdminSession.existsUser(admin, username)) {
      return "NO_SUCH_USER";
    }
    Collection<Certificate> certificates = certificateStoreSession.findCertificatesByUsername(admin, username);
    Iterator<Certificate> iter = certificates.iterator();
    if (!iter.hasNext()) {
      return "NO_CERTIFICATES";
    }
    while (iter.hasNext()) {
      X509Certificate cert = (X509Certificate)iter.next();
      try {
        cert.checkValidity(new Date(System.currentTimeMillis() + 14 * 24 * 3600 * 1000));
        return "OK";
      } catch (CertificateExpiredException e) {
        try {
          cert.checkValidity(new Date(System.currentTimeMillis()));
          return "EXPIRING";
        } catch (CertificateExpiredException e1) {
        } catch (CertificateNotYetValidException e1) {
          return "ERROR";
        }
      } catch (CertificateNotYetValidException e) {
        return "ERROR";
      }
    }
    return "EXPIRED";
  }

}
TOP

Related Classes of org.ejbca.ui.web.pub.AutoEnrollServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.