/* * Password Management Servlets (PWM) * http://www.pwm-project.org * * Copyright (c) 2006-2009 Novell, Inc. * Copyright (c) 2009-2017 The PWM Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package password.pwm.http.servlet.configmanager; import com.novell.ldapchai.exception.ChaiUnavailableException; import org.apache.commons.fileupload.servlet.ServletFileUpload; import password.pwm.AppProperty; import password.pwm.PwmApplication; import password.pwm.PwmApplicationMode; import password.pwm.PwmConstants; import password.pwm.config.Configuration; import password.pwm.error.ErrorInformation; import password.pwm.error.PwmError; import password.pwm.error.PwmException; import password.pwm.error.PwmUnrecoverableException; import password.pwm.http.ContextManager; import password.pwm.http.HttpHeader; import password.pwm.http.HttpMethod; import password.pwm.http.JspUrl; import password.pwm.http.PwmRequest; import password.pwm.http.PwmResponse; import password.pwm.http.servlet.AbstractPwmServlet; import password.pwm.i18n.Message; import password.pwm.util.java.JavaHelper; import password.pwm.util.java.TimeDuration; import password.pwm.util.localdb.LocalDB; import password.pwm.util.localdb.LocalDBFactory; import password.pwm.util.localdb.LocalDBUtility; import password.pwm.util.logging.PwmLogLevel; import password.pwm.util.logging.PwmLogger; import password.pwm.ws.server.RestResultBean; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.time.Instant; import java.util.Collection; import java.util.Collections; @WebServlet( name = "ConfigManagerLocalDBServlet", urlPatterns = { PwmConstants.URL_PREFIX_PRIVATE + "/config/manager/localdb", } ) public class ConfigManagerLocalDBServlet extends AbstractPwmServlet { private static final PwmLogger LOGGER = PwmLogger.forClass(ConfigManagerLocalDBServlet.class); public enum ConfigManagerAction implements ProcessAction { exportLocalDB(HttpMethod.GET), importLocalDB(HttpMethod.POST), ; private final HttpMethod method; ConfigManagerAction(final HttpMethod method) { this.method = method; } public Collection<HttpMethod> permittedMethods() { return Collections.singletonList(method); } } protected ConfigManagerAction readProcessAction(final PwmRequest request) throws PwmUnrecoverableException { try { return ConfigManagerAction.valueOf(request.readParameterAsString(PwmConstants.PARAM_ACTION_REQUEST)); } catch (IllegalArgumentException e) { return null; } } protected void processAction(final PwmRequest pwmRequest) throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException { final ConfigManagerAction processAction = readProcessAction(pwmRequest); if (processAction != null) { switch (processAction) { case exportLocalDB: doExportLocalDB(pwmRequest); break; case importLocalDB: restUploadLocalDB(pwmRequest); return; default: JavaHelper.unhandledSwitchStatement(processAction); } return; } pwmRequest.forwardToJsp(JspUrl.CONFIG_MANAGER_LOCALDB); } private void doExportLocalDB(final PwmRequest pwmRequest) throws IOException, ServletException, PwmUnrecoverableException { final PwmResponse resp = pwmRequest.getPwmResponse(); final Instant startTime = Instant.now(); resp.setHeader(HttpHeader.ContentDisposition, "attachment;filename=" + PwmConstants.PWM_APP_NAME + "-LocalDB.bak"); resp.setContentType(PwmConstants.ContentTypeValue.octetstream); resp.setHeader(HttpHeader.ContentTransferEncoding, "binary"); final LocalDBUtility localDBUtility = new LocalDBUtility(pwmRequest.getPwmApplication().getLocalDB()); try { final int bufferSize = Integer.parseInt(pwmRequest.getConfig().readAppProperty(AppProperty.HTTP_DOWNLOAD_BUFFER_SIZE)); final OutputStream bos = new BufferedOutputStream(resp.getOutputStream(),bufferSize); localDBUtility.exportLocalDB(bos, LOGGER.asAppendable(PwmLogLevel.DEBUG, pwmRequest.getSessionLabel()), true); LOGGER.debug(pwmRequest, "completed localDBExport process in " + TimeDuration.fromCurrent(startTime).asCompactString()); } catch (Exception e) { LOGGER.error(pwmRequest, "error downloading export localdb: " + e.getMessage()); } } void restUploadLocalDB(final PwmRequest pwmRequest) throws IOException, ServletException, PwmUnrecoverableException { final PwmApplication pwmApplication = pwmRequest.getPwmApplication(); final HttpServletRequest req = pwmRequest.getHttpServletRequest(); if (pwmApplication.getApplicationMode() == PwmApplicationMode.RUNNING) { final String errorMsg = "database upload is not permitted when in running mode"; final ErrorInformation errorInformation = new ErrorInformation(PwmError.CONFIG_UPLOAD_FAILURE,errorMsg,new String[]{errorMsg}); pwmRequest.respondWithError(errorInformation, true); return; } if (!ServletFileUpload.isMultipartContent(req)) { final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN,"no file found in upload"); pwmRequest.outputJsonResult(RestResultBean.fromError(errorInformation, pwmRequest)); LOGGER.error(pwmRequest, "error during database import: " + errorInformation.toDebugStr()); return; } final InputStream inputStream = pwmRequest.readFileUploadStream(PwmConstants.PARAM_FILE_UPLOAD); final ContextManager contextManager = ContextManager.getContextManager(pwmRequest); LocalDB localDB = null; try { final File localDBLocation = pwmApplication.getLocalDB().getFileLocation(); final Configuration configuration = pwmApplication.getConfig(); contextManager.shutdown(); localDB = LocalDBFactory.getInstance(localDBLocation, false, null, configuration); final LocalDBUtility localDBUtility = new LocalDBUtility(localDB); LOGGER.info(pwmRequest, "beginning LocalDB import"); localDBUtility.importLocalDB(inputStream, LOGGER.asAppendable(PwmLogLevel.DEBUG, pwmRequest.getSessionLabel())); LOGGER.info(pwmRequest, "completed LocalDB import"); } catch (Exception e) { final ErrorInformation errorInformation = e instanceof PwmException ? ((PwmException) e).getErrorInformation() : new ErrorInformation(PwmError.ERROR_UNKNOWN,e.getMessage()); pwmRequest.outputJsonResult(RestResultBean.fromError(errorInformation, pwmRequest)); LOGGER.error(pwmRequest, "error during LocalDB import: " + errorInformation.toDebugStr()); return; } finally { if (localDB != null) { try { localDB.close(); } catch (Exception e) { LOGGER.error(pwmRequest, "error closing LocalDB after import process: " + e.getMessage()); } } contextManager.initialize(); } pwmRequest.outputJsonResult(RestResultBean.forSuccessMessage(pwmRequest, Message.Success_Unknown)); } }