use of password.pwm.error.ErrorInformation in project pwm by pwm-project.
the class RequestInitializationFilter method handleRequestSecurityChecks.
@SuppressWarnings("checkstyle:MethodLength")
public static void handleRequestSecurityChecks(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
final LocalSessionStateBean ssBean = pwmRequest.getPwmSession().getSessionStateBean();
// check the user's IP address
if (!pwmRequest.getConfig().readSettingAsBoolean(PwmSetting.MULTI_IP_SESSION_ALLOWED)) {
final String remoteAddress = readUserIPAddress(pwmRequest.getHttpServletRequest(), pwmRequest.getConfig());
if (!ssBean.getSrcAddress().equals(remoteAddress)) {
final String errorMsg = "current network address '" + remoteAddress + "' has changed from original network address '" + ssBean.getSrcAddress() + "'";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, errorMsg);
throw new PwmUnrecoverableException(errorInformation);
}
}
// check total time.
{
if (ssBean.getSessionCreationTime() != null) {
final Long maxSessionSeconds = pwmRequest.getConfig().readSettingAsLong(PwmSetting.SESSION_MAX_SECONDS);
final TimeDuration sessionAge = TimeDuration.fromCurrent(ssBean.getSessionCreationTime());
if (sessionAge.getTotalSeconds() > maxSessionSeconds) {
final String errorMsg = "session age (" + sessionAge.asCompactString() + ") is longer than maximum permitted age";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, errorMsg);
throw new PwmUnrecoverableException(errorInformation);
}
}
}
// check headers
{
final List<String> requiredHeaders = pwmRequest.getConfig().readSettingAsStringArray(PwmSetting.REQUIRED_HEADERS);
if (requiredHeaders != null && !requiredHeaders.isEmpty()) {
final Map<String, String> configuredValues = StringUtil.convertStringListToNameValuePair(requiredHeaders, "=");
for (final Map.Entry<String, String> entry : configuredValues.entrySet()) {
final String key = entry.getKey();
if (key != null && key.length() > 0) {
final String requiredValue = entry.getValue();
if (requiredValue != null && requiredValue.length() > 0) {
final String value = pwmRequest.readHeaderValueAsString(key);
if (value == null || value.length() < 1) {
final String errorMsg = "request is missing required value for header '" + key + "'";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, errorMsg);
throw new PwmUnrecoverableException(errorInformation);
} else {
if (!requiredValue.equals(value)) {
final String errorMsg = "request has incorrect required value for header '" + key + "'";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, errorMsg);
throw new PwmUnrecoverableException(errorInformation);
}
}
}
}
}
}
}
// check permitted source IP address
{
final List<String> requiredHeaders = pwmRequest.getConfig().readSettingAsStringArray(PwmSetting.IP_PERMITTED_RANGE);
if (requiredHeaders != null && !requiredHeaders.isEmpty()) {
boolean match = false;
final String requestAddress = pwmRequest.getHttpServletRequest().getRemoteAddr();
for (int i = 0; i < requiredHeaders.size() && !match; i++) {
final String ipMatchString = requiredHeaders.get(i);
try {
final IPMatcher ipMatcher = new IPMatcher(ipMatchString);
try {
if (ipMatcher.match(requestAddress)) {
match = true;
}
} catch (IPMatcher.IPMatcherException e) {
LOGGER.error("error while attempting to match permitted address range '" + ipMatchString + "', error: " + e);
}
} catch (IPMatcher.IPMatcherException e) {
LOGGER.error("error parsing permitted address range '" + ipMatchString + "', error: " + e);
}
}
if (!match) {
final String errorMsg = "request network address '" + requestAddress + "' does not match any configured permitted source address";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, errorMsg);
throw new PwmUnrecoverableException(errorInformation);
}
}
}
// csrf cross-site request forgery checks
final boolean performCsrfHeaderChecks = Boolean.parseBoolean(pwmRequest.getConfig().readAppProperty(AppProperty.SECURITY_HTTP_PERFORM_CSRF_HEADER_CHECKS));
if (performCsrfHeaderChecks && !pwmRequest.getMethod().isIdempotent() && !pwmRequest.getURL().isRestService()) {
final String originValue = pwmRequest.readHeaderValueAsString(HttpHeader.Origin);
final String referrerValue = pwmRequest.readHeaderValueAsString(HttpHeader.Referer);
final String siteUrl = pwmRequest.getPwmApplication().getConfig().readSettingAsString(PwmSetting.PWM_SITE_URL);
final String targetValue = pwmRequest.getHttpServletRequest().getRequestURL().toString();
if (StringUtil.isEmpty(targetValue)) {
final String msg = "malformed request instance, missing target uri value";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, msg);
LOGGER.debug(pwmRequest, errorInformation.toDebugStr() + " [" + makeHeaderDebugStr(pwmRequest) + "]");
throw new PwmUnrecoverableException(errorInformation);
}
final boolean originHeaderEvaluated;
if (!StringUtil.isEmpty(originValue)) {
if (!PwmURL.compareUriBase(originValue, targetValue)) {
final String msg = "cross-origin request not permitted: origin header does not match incoming target url" + " [" + makeHeaderDebugStr(pwmRequest) + "]";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, msg);
LOGGER.debug(pwmRequest, errorInformation.toDebugStr());
throw new PwmUnrecoverableException(errorInformation);
}
originHeaderEvaluated = true;
} else {
originHeaderEvaluated = false;
}
final boolean referrerHeaderEvaluated;
if (!StringUtil.isEmpty(referrerValue)) {
if (!PwmURL.compareUriBase(referrerValue, targetValue) && !PwmURL.compareUriBase(referrerValue, siteUrl)) {
final String msg = "cross-origin request not permitted: referrer header does not match incoming target url" + " [" + makeHeaderDebugStr(pwmRequest) + "]";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, msg);
LOGGER.debug(pwmRequest, errorInformation.toDebugStr());
throw new PwmUnrecoverableException(errorInformation);
}
referrerHeaderEvaluated = true;
} else {
referrerHeaderEvaluated = false;
}
if (!referrerHeaderEvaluated && !originHeaderEvaluated && !PwmURL.compareUriBase(originValue, siteUrl)) {
final String msg = "neither referer nor origin header request are present on non-idempotent request";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION, msg);
LOGGER.debug(pwmRequest, errorInformation.toDebugStr() + " [" + makeHeaderDebugStr(pwmRequest) + "]");
throw new PwmUnrecoverableException(errorInformation);
}
}
// check trial
if (PwmConstants.TRIAL_MODE) {
final StatisticsManager statisticsManager = pwmRequest.getPwmApplication().getStatisticsManager();
final String currentAuthString = statisticsManager.getStatBundleForKey(StatisticsManager.KEY_CURRENT).getStatistic(Statistic.AUTHENTICATIONS);
if (new BigInteger(currentAuthString).compareTo(BigInteger.valueOf(PwmConstants.TRIAL_MAX_AUTHENTICATIONS)) > 0) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_TRIAL_VIOLATION, "maximum usage per server startup exceeded"));
}
final String totalAuthString = statisticsManager.getStatBundleForKey(StatisticsManager.KEY_CUMULATIVE).getStatistic(Statistic.AUTHENTICATIONS);
if (new BigInteger(totalAuthString).compareTo(BigInteger.valueOf(PwmConstants.TRIAL_MAX_TOTAL_AUTH)) > 0) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_TRIAL_VIOLATION, "maximum usage for this server has been exceeded"));
}
}
// check intruder
pwmRequest.getPwmApplication().getIntruderManager().convenience().checkAddressAndSession(pwmRequest.getPwmSession());
}
use of password.pwm.error.ErrorInformation in project pwm by pwm-project.
the class AbstractPwmServlet method handleRequest.
private void handleRequest(final HttpServletRequest req, final HttpServletResponse resp, final HttpMethod method) throws ServletException, IOException {
try {
final PwmRequest pwmRequest = PwmRequest.forRequest(req, resp);
if (!method.isIdempotent() && !pwmRequest.getURL().isCommandServletURL()) {
Validator.validatePwmFormID(pwmRequest);
try {
Validator.validatePwmRequestCounter(pwmRequest);
} catch (PwmOperationalException e) {
if (e.getError() == PwmError.ERROR_INCORRECT_REQ_SEQUENCE) {
final ErrorInformation errorInformation = e.getErrorInformation();
final PwmSession pwmSession = PwmSessionWrapper.readPwmSession(req);
LOGGER.error(pwmSession, errorInformation.toDebugStr());
pwmRequest.respondWithError(errorInformation, false);
return;
}
throw e;
}
}
// check for incorrect method type.
final ProcessAction processAction = readProcessAction(pwmRequest);
if (processAction != null) {
if (!processAction.permittedMethods().contains(method)) {
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SERVICE_NOT_AVAILABLE, "incorrect request method " + method.toString() + " on request to " + pwmRequest.getURLwithQueryString());
LOGGER.error(pwmRequest.getPwmSession(), errorInformation.toDebugStr());
pwmRequest.respondWithError(errorInformation, false);
return;
}
}
this.processAction(pwmRequest);
} catch (Exception e) {
final PwmRequest pwmRequest;
try {
pwmRequest = PwmRequest.forRequest(req, resp);
} catch (Exception e2) {
try {
LOGGER.fatal("exception occurred, but exception handler unable to load request instance; error=" + e.getMessage(), e);
} catch (Exception e3) {
e3.printStackTrace();
}
throw new ServletException(e);
}
final PwmUnrecoverableException pue = convertToPwmUnrecoverableException(e, pwmRequest);
if (processUnrecoverableException(req, resp, pwmRequest.getPwmApplication(), pwmRequest.getPwmSession(), pue)) {
return;
}
outputUnrecoverableException(pwmRequest, pue);
clearModuleBeans(pwmRequest);
}
}
use of password.pwm.error.ErrorInformation in project pwm by pwm-project.
the class ControlledPwmServlet method dispatchMethod.
private ProcessStatus dispatchMethod(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
final ProcessAction action = readProcessAction(pwmRequest);
if (action == null) {
return ProcessStatus.Continue;
}
try {
final Method interestedMethod = discoverMethodForAction(this.getClass(), action);
if (interestedMethod != null) {
interestedMethod.setAccessible(true);
return (ProcessStatus) interestedMethod.invoke(this, pwmRequest);
}
} catch (InvocationTargetException e) {
final Throwable cause = e.getCause();
if (cause != null) {
if (cause instanceof PwmUnrecoverableException) {
throw (PwmUnrecoverableException) cause;
}
final String msg = "unexpected error during action handler for '" + this.getClass().getName() + ":" + action + "', error: " + cause.getMessage();
LOGGER.error(pwmRequest, msg, e.getCause());
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNKNOWN, msg));
}
LOGGER.error("uncased invocation error: " + e.getMessage(), e);
} catch (Throwable e) {
final String msg = "unexpected error invoking action handler for '" + action + "', error: " + e.getMessage();
LOGGER.error(msg, e);
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNKNOWN, msg));
}
final String msg = "missing action handler for '" + action + "'";
LOGGER.error(msg);
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNKNOWN, msg));
}
use of password.pwm.error.ErrorInformation in project pwm by pwm-project.
the class ApplianceStatusChecker method figureUrl.
private String figureUrl(final PwmApplication pwmApplication) throws IOException, PwmOperationalException {
final String hostnameFile = pwmApplication.getPwmEnvironment().getParameters().get(PwmEnvironment.ApplicationParameter.ApplianceHostnameFile);
if (StringUtil.isEmpty(hostnameFile)) {
final String msg = "unable to determine appliance hostname, hostname file environment param " + PwmEnvironment.ApplicationParameter.ApplianceHostnameFile.toString() + " is not set";
throw new PwmOperationalException(new ErrorInformation(PwmError.ERROR_UNKNOWN, msg));
}
final String hostname = readFileContents(hostnameFile);
final String port = pwmApplication.getPwmEnvironment().getParameters().get(PwmEnvironment.ApplicationParameter.AppliancePort);
final String url = "https://" + hostname + ":" + port + "/sspr/appliance-update-status";
LOGGER.trace(SessionLabel.HEALTH_SESSION_LABEL, "calculated appliance host url as: " + url);
return url;
}
use of password.pwm.error.ErrorInformation in project pwm by pwm-project.
the class AuthenticationFilter method processAuthenticatedSession.
private void processAuthenticatedSession(final PwmRequest pwmRequest, final PwmFilterChain chain) throws IOException, ServletException, PwmUnrecoverableException {
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final PwmSession pwmSession = pwmRequest.getPwmSession();
// read the basic auth info out of the header (if it exists);
if (pwmRequest.getConfig().readSettingAsBoolean(PwmSetting.BASIC_AUTH_ENABLED)) {
final BasicAuthInfo basicAuthInfo = BasicAuthInfo.parseAuthHeader(pwmApplication, pwmRequest);
final BasicAuthInfo originalBasicAuthInfo = pwmSession.getLoginInfoBean().getBasicAuth();
// check to make sure basic auth info is same as currently known user in session.
if (basicAuthInfo != null && originalBasicAuthInfo != null && !(originalBasicAuthInfo.equals(basicAuthInfo))) {
// if we read here then user is using basic auth, and header has changed since last request
// this means something is screwy, so log out the session
// read the current user info for logging
final UserInfo userInfo = pwmSession.getUserInfo();
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_BAD_SESSION, "basic auth header user '" + basicAuthInfo.getUsername() + "' does not match currently logged in user '" + userInfo.getUserIdentity() + "', session will be logged out");
LOGGER.info(pwmRequest, errorInformation);
// log out their user
pwmSession.unauthenticateUser(pwmRequest);
// send en error to user.
pwmRequest.respondWithError(errorInformation, true);
return;
}
}
// check status of oauth expiration
if (pwmSession.getLoginInfoBean().getOauthExp() != null) {
final OAuthSettings oauthSettings = OAuthSettings.forSSOAuthentication(pwmRequest.getConfig());
final OAuthMachine oAuthMachine = new OAuthMachine(oauthSettings);
if (oAuthMachine.checkOAuthExpiration(pwmRequest)) {
pwmRequest.respondWithError(new ErrorInformation(PwmError.ERROR_OAUTH_ERROR, "oauth access token has expired"));
return;
}
}
handleAuthenticationCookie(pwmRequest);
if (forceRequiredRedirects(pwmRequest) == ProcessStatus.Halt) {
return;
}
// user session is authed, and session and auth header match, so forward request on.
chain.doFilter();
}
Aggregations