Removed untrusted data from exception messages in case they end up on the webpage

This commit is contained in:
Aurora Lahtela 2023-01-15 10:04:10 +02:00
parent f20a04809c
commit 9e11d9f484
19 changed files with 37 additions and 145 deletions

View File

@ -24,7 +24,7 @@ import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resource.WebResource;
import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.identification.Server;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.PluginSettings;
@ -200,7 +200,7 @@ public class NetworkPageExporter extends FileExporter {
private Optional<Response> getJSONResponse(String resource) {
try {
return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) {
} catch (WebUserAuthException e) {
// The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e, e);
}

View File

@ -24,7 +24,7 @@ import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resource.WebResource;
import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.PluginSettings;
import com.djrapitops.plan.settings.theme.Theme;
@ -153,7 +153,7 @@ public class PlayerPageExporter extends FileExporter {
private Optional<Response> getJSONResponse(String resource) {
try {
return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) {
} catch (WebUserAuthException e) {
// The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e, e);
}

View File

@ -24,7 +24,7 @@ import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resource.WebResource;
import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.PluginSettings;
@ -142,7 +142,7 @@ public class PlayersPageExporter extends FileExporter {
private Optional<Response> getJSONResponse(String resource) {
try {
return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) {
} catch (WebUserAuthException e) {
// The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e.toString(), e);
}

View File

@ -20,7 +20,7 @@ import com.djrapitops.plan.delivery.web.AssetVersions;
import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
import com.djrapitops.plan.settings.locale.LangCode;
@ -179,7 +179,7 @@ public class ReactExporter extends FileExporter {
private Optional<Response> getJsonResponse(String resource) {
try {
return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) {
} catch (WebUserAuthException e) {
// The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e, e);
}

View File

@ -24,7 +24,7 @@ import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resource.WebResource;
import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver;
import com.djrapitops.plan.exceptions.connection.WebException;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.identification.Server;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.identification.ServerUUID;
@ -224,7 +224,7 @@ public class ServerPageExporter extends FileExporter {
private Optional<Response> getJSONResponse(String resource) {
try {
return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap()));
} catch (WebException e) {
} catch (WebUserAuthException e) {
// The rest of the exceptions should not be thrown
throw new IllegalStateException("Unexpected exception thrown: " + e, e);
}

View File

@ -42,7 +42,7 @@ public class InternalErrorPage implements Page {
private final VersionChecker versionChecker;
public InternalErrorPage(
String template, String errorMsg, Throwable error,
String template, String errorMsg, @Untrusted Throwable error,
VersionChecker versionChecker
) {
this.template = template;

View File

@ -38,6 +38,7 @@ import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.file.PlanFiles;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.version.VersionChecker;
import dagger.Lazy;
import org.apache.commons.lang3.StringUtils;
@ -219,7 +220,7 @@ public class PageFactory {
);
}
public Page internalErrorPage(String message, Throwable error) {
public Page internalErrorPage(String message, @Untrusted Throwable error) {
try {
return new InternalErrorPage(
getResource("error.html"), message, error,

View File

@ -96,7 +96,7 @@ public class ResponseFactory {
.build();
}
private Response forInternalError(Throwable error, String cause) {
private Response forInternalError(@Untrusted Throwable error, String cause) {
return Response.builder()
.setMimeType(MimeType.HTML)
.setContent(pageFactory.internalErrorPage(cause, error).toHtml())
@ -171,7 +171,7 @@ public class ResponseFactory {
.build();
}
public Response javaScriptResponse(String fileName) {
public Response javaScriptResponse(@Untrusted String fileName) {
try {
String content = UnaryChain.of(getResource(fileName).asString())
.chain(this::replaceMainAddressPlaceholder)
@ -189,7 +189,7 @@ public class ResponseFactory {
.setStatus(200)
.build();
} catch (UncheckedIOException e) {
return notFound404("JS File not found from jar: " + fileName + ", " + e);
return notFound404("Javascript File not found");
}
}
@ -217,11 +217,11 @@ public class ResponseFactory {
.setStatus(200)
.build();
} catch (UncheckedIOException e) {
return notFound404("CSS File not found from jar: " + fileName + ", " + e);
return notFound404("CSS File not found");
}
}
public Response imageResponse(String fileName) {
public Response imageResponse(@Untrusted String fileName) {
try {
return Response.builder()
.setMimeType(MimeType.IMAGE)
@ -229,11 +229,11 @@ public class ResponseFactory {
.setStatus(200)
.build();
} catch (UncheckedIOException e) {
return notFound404("Image File not found from jar: " + fileName + ", " + e);
return notFound404("Image File not found");
}
}
public Response fontResponse(String fileName) {
public Response fontResponse(@Untrusted String fileName) {
String type;
if (fileName.endsWith(".woff")) {
type = MimeType.FONT_WOFF;
@ -252,7 +252,7 @@ public class ResponseFactory {
.setContent(getResource(fileName))
.build();
} catch (UncheckedIOException e) {
return notFound404("Font File not found from jar: " + fileName + ", " + e);
return notFound404("Font File not found");
}
}

View File

@ -33,7 +33,6 @@ import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver;
import com.djrapitops.plan.delivery.webserver.resolver.swagger.SwaggerJsonResolver;
import com.djrapitops.plan.delivery.webserver.resolver.swagger.SwaggerPageResolver;
import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.ForbiddenException;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger;
@ -173,8 +172,6 @@ public class ResponseResolver {
return tryToGetResponse(request);
} catch (NotFoundException e) {
return responseFactory.notFound404(e.getMessage());
} catch (ForbiddenException e) {
return responseFactory.forbidden403(e.getMessage());
} catch (BadRequestException e) {
return responseFactory.badRequest(e.getMessage(), request.getPath().asString());
} catch (WebUserAuthException e) {
@ -187,7 +184,6 @@ public class ResponseResolver {
/**
* @throws NotFoundException In some cases when page was not found, not all.
* @throws ForbiddenException If the user is not allowed to see the page
* @throws BadRequestException If the request did not have required things.
*/
private Response tryToGetResponse(@Untrusted Request request) {

View File

@ -164,7 +164,7 @@ public class QueryJSONResolver implements Resolver {
.orElseThrow(() -> new BadRequestException("'view' parameter not set (expecting json object {afterDate, afterTime, beforeDate, beforeTime})"));
return new InputQueryDto(view, queryFilters);
} catch (IOException e) {
throw new BadRequestException("Failed to decode json: '" + q + "', " + e.getMessage());
throw new BadRequestException("Failed to decode json");
}
}
@ -202,7 +202,7 @@ public class QueryJSONResolver implements Resolver {
.setJSONContent(stored.json)
.build();
} catch (ParseException e) {
throw new BadRequestException("'view' date format was incorrect (expecting afterDate dd/mm/yyyy, afterTime hh:mm, beforeDate dd/mm/yyyy, beforeTime hh:mm}): " + e.getMessage());
throw new BadRequestException("'view' date format was incorrect (expecting afterDate dd/mm/yyyy, afterTime hh:mm, beforeDate dd/mm/yyyy, beforeTime hh:mm})");
}
}

View File

@ -79,7 +79,7 @@ public class ServerIdentityJSONResolver implements Resolver {
@Untrusted String serverIdentifier = request.getQuery().get("server")
.orElseThrow(() -> new BadRequestException("Missing 'server' query parameter"));
ServerDto server = jsonFactory.serverForIdentifier(serverIdentifier)
.orElseThrow(() -> new NotFoundException("Server with identifier '" + serverIdentifier + "' was not found in the database"));
.orElseThrow(() -> new NotFoundException("Server with given identifier was not found in the database"));
return Optional.of(Response.builder()
.setJSONContent(server)
.build());

View File

@ -1,24 +0,0 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.exceptions;
public class MissingPipelineException extends IllegalStateException {
public MissingPipelineException() {
super("A data service pipeline is missing!");
}
}

View File

@ -17,14 +17,13 @@
package com.djrapitops.plan.exceptions;
import com.djrapitops.plan.delivery.webserver.auth.FailReason;
import com.djrapitops.plan.exceptions.connection.WebException;
/**
* Thrown when WebUser can not be authorized (WebServer).
*
* @author AuroraLS3
*/
public class WebUserAuthException extends WebException {
public class WebUserAuthException extends IllegalStateException {
private final FailReason failReason;

View File

@ -1,28 +0,0 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.exceptions.connection;
/**
* Thrown when Connection gets a 403 response.
*
* @author AuroraLS3
*/
public class ForbiddenException extends WebException {
public ForbiddenException(String url) {
super("Forbidden: " + url);
}
}

View File

@ -1,40 +0,0 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.exceptions.connection;
/**
* Thrown when Connection POST-request fails, general Exception.
*
* @author AuroraLS3
*/
public class WebException extends IllegalStateException {
public WebException() {
}
public WebException(String message) {
super(message);
}
public WebException(String message, Throwable cause) {
super(message, cause);
}
public WebException(Throwable cause) {
super(cause);
}
}

View File

@ -74,8 +74,8 @@ public class Identifiers {
return Optional.empty();
}
return Optional.of(timestamp);
} catch (NumberFormatException nonNumberTimestamp) {
throw new BadRequestException("'timestamp' was not a number: " + nonNumberTimestamp.getMessage());
} catch (@Untrusted NumberFormatException nonNumberTimestamp) {
throw new BadRequestException("'timestamp' was not a number");
}
}

View File

@ -96,7 +96,7 @@ public class QueryFilters {
private Filter.Result apply(Filter.Result current, @Untrusted InputFilterDto inputFilterDto) {
@Untrusted String kind = inputFilterDto.getKind();
Filter filter = getFilter(kind).orElseThrow(() -> new BadRequestException("Filter kind not supported: '" + kind + "'"));
Filter filter = getFilter(kind).orElseThrow(() -> new BadRequestException("Given Filter 'kind' not supported"));
return getResult(current, filter, inputFilterDto);
}
@ -106,8 +106,7 @@ public class QueryFilters {
return current == null ? filter.apply(query) : current.apply(filter, query);
} catch (IllegalArgumentException badOptions) {
throw new BadRequestException("Bad parameters for filter '" + filter.getKind() +
"': expecting " + Arrays.asList(filter.getExpectedParameters()) +
", but was given " + query.getSetParameters());
"': expecting " + Arrays.asList(filter.getExpectedParameters()) + " as parameters");
}
}

View File

@ -76,8 +76,8 @@ public abstract class DateRangeFilter implements Filter {
try {
return dateFormat.parse(date + ' ' + time).getTime();
} catch (ParseException e) {
throw new IllegalArgumentException(e);
} catch (@Untrusted ParseException e) {
throw new IllegalArgumentException("Could not parse date from given '" + dateKey + "' and '" + timeKey + "' - expected format dd/MM/yyyy and kk:mm");
}
}
}

View File

@ -16,11 +16,7 @@
*/
package com.djrapitops.plan.delivery.webserver;
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException;
import com.djrapitops.plan.delivery.webserver.http.WebServer;
import com.djrapitops.plan.exceptions.connection.ForbiddenException;
import com.djrapitops.plan.exceptions.connection.WebException;
import org.apache.commons.compress.utils.IOUtils;
import org.junit.jupiter.api.Test;
import utilities.HTTPConnector;
@ -68,19 +64,12 @@ interface HttpsServerTest {
int responseCode = connection.getResponseCode();
switch (responseCode) {
case 200:
case 302:
return;
case 400:
throw new BadRequestException("Bad Request: " + address);
case 403:
throw new ForbiddenException(address + " returned 403");
case 404:
throw new NotFoundException(address + " returned a 404, ensure that your server is connected to an up to date Plan server.");
case 500:
throw new IllegalStateException(); // Not supported
default:
throw new WebException(address + "| Wrong response code " + responseCode);
case 200, 302 -> {}
case 400 -> throw new IllegalStateException("Bad Request: " + address);
case 403 -> throw new IllegalStateException(address + " returned 403");
case 404 -> throw new IllegalStateException(address + " returned a 404.");
case 500 -> throw new IllegalStateException(); // Not supported
default -> throw new IllegalStateException(address + "| Wrong response code " + responseCode);
}
} finally {
connection.disconnect();