Add ip validations where needed

This commit is contained in:
Colin McDonald 2016-07-25 20:58:52 -04:00
parent e827a30131
commit 4b0d66985e
14 changed files with 115 additions and 19 deletions

10
pom.xml
View File

@ -67,27 +67,27 @@
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId> <artifactId>vertx-core</artifactId>
<version>3.3.1</version> <version>3.3.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId> <artifactId>vertx-web</artifactId>
<version>3.3.1</version> <version>3.3.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-redis-client</artifactId> <artifactId>vertx-redis-client</artifactId>
<version>3.3.1</version> <version>3.3.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-circuit-breaker</artifactId> <artifactId>vertx-circuit-breaker</artifactId>
<version>3.3.1</version> <version>3.3.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-dropwizard-metrics</artifactId> <artifactId>vertx-dropwizard-metrics</artifactId>
<version>3.3.1</version> <version>3.3.2</version>
</dependency> </dependency>
<!-- Google Libs --> <!-- Google Libs -->

View File

@ -105,6 +105,7 @@ import net.frozenorb.apiv3.serialization.mongodb.UuidCodecProvider;
import net.frozenorb.apiv3.util.EmailUtils; import net.frozenorb.apiv3.util.EmailUtils;
import net.frozenorb.apiv3.util.MojangUtils; import net.frozenorb.apiv3.util.MojangUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.UserSessionUtils;
import org.bson.Document; import org.bson.Document;
import org.bson.codecs.BsonValueCodecProvider; import org.bson.codecs.BsonValueCodecProvider;
import org.bson.codecs.DocumentCodecProvider; import org.bson.codecs.DocumentCodecProvider;
@ -139,6 +140,29 @@ public final class APIv3 extends AbstractVerticle {
setupMetrics(); setupMetrics();
setupHttpServer(); setupHttpServer();
UserSessionUtils.setupRedis();
try {
Thread.sleep(2000L);
} catch (Exception ex) {
ex.printStackTrace();
}
UserSessionUtils.createSession(UUID.randomUUID(), "192.168.1.1", (v, i) -> {
if (i == null) {
System.out.println("a: " + v);
} else {
i.printStackTrace();
}
});
UserSessionUtils.createSession(UUID.randomUUID(), "::1", (v, i) -> {
if (i == null) {
System.out.println("b: " + v);
} else {
i.printStackTrace();
}
});
/*User.findAll((users, error) -> { /*User.findAll((users, error) -> {
if (error != null) { if (error != null) {
error.printStackTrace(); error.printStackTrace();

View File

@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j;
import net.frozenorb.apiv3.actor.Actor; import net.frozenorb.apiv3.actor.Actor;
import net.frozenorb.apiv3.actor.ActorType; import net.frozenorb.apiv3.actor.ActorType;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.UserSessionUtils; import net.frozenorb.apiv3.util.UserSessionUtils;
@Slf4j @Slf4j
@ -30,6 +31,11 @@ public final class WebsiteUserSessionHandler implements Handler<RoutingContext>
String userSession = ctx.request().getHeader("MHQ-UserSession"); String userSession = ctx.request().getHeader("MHQ-UserSession");
String userIp = ctx.request().getHeader("MHQ-UserIp"); String userIp = ctx.request().getHeader("MHQ-UserIp");
if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid.");
return;
}
UserSessionUtils.sessionExists(userIp, userSession, (exists, error) -> { UserSessionUtils.sessionExists(userIp, userSession, (exists, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);

View File

@ -9,6 +9,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog;
import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.auditLog.AuditLogActionType;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.PasswordUtils; import net.frozenorb.apiv3.util.PasswordUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
@ -57,8 +58,14 @@ public final class POSTEmailTokensIdConfirm implements Handler<RoutingContext> {
user.completeEmailRegistration(user.getPendingEmail()); user.completeEmailRegistration(user.getPendingEmail());
user.updatePassword(password); user.updatePassword(password);
SyncUtils.<Void>runBlocking(v -> user.save(v)); SyncUtils.<Void>runBlocking(v -> user.save(v));
String userIp = requestBody.getString("userIp");
AuditLog.log(user.getId(), requestBody.getString("userIp"), ctx, AuditLogActionType.USER_CONFIRM_EMAIL, (ignored, error) -> { if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, AuditLogActionType.USER_CONFIRM_EMAIL, (ignored, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {

View File

@ -5,6 +5,7 @@ import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.model.IpBan; import net.frozenorb.apiv3.model.IpBan;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.UuidUtils; import net.frozenorb.apiv3.util.UuidUtils;
import org.bson.Document; import org.bson.Document;
@ -14,8 +15,14 @@ public final class GETIpBans implements Handler<RoutingContext> {
try { try {
int skip = ctx.request().getParam("skip") == null ? 0 : Integer.parseInt(ctx.request().getParam("skip")); int skip = ctx.request().getParam("skip") == null ? 0 : Integer.parseInt(ctx.request().getParam("skip"));
int pageSize = ctx.request().getParam("pageSize") == null ? 100 : Integer.parseInt(ctx.request().getParam("pageSize")); int pageSize = ctx.request().getParam("pageSize") == null ? 100 : Integer.parseInt(ctx.request().getParam("pageSize"));
String userIp = ctx.request().getParam("userIp");
IpBan.findPaginated(ctx.request().getParam("userIp") == null ? new Document() : new Document("userIp", UuidUtils.parseUuid(ctx.request().getParam("user"))), skip, pageSize, (grants, error) -> { if (userIp != null && !IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
IpBan.findPaginated(userIp == null ? new Document() : new Document("userIp", userIp), skip, pageSize, (grants, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {

View File

@ -14,6 +14,7 @@ import net.frozenorb.apiv3.model.Punishment;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.Permissions; import net.frozenorb.apiv3.unsorted.Permissions;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
import java.time.Instant; import java.time.Instant;
@ -96,6 +97,9 @@ public final class POSTPunishments implements Handler<RoutingContext> {
if (latestIpLogEntry != null) { if (latestIpLogEntry != null) {
userIp = latestIpLogEntry.getUserIp(); userIp = latestIpLogEntry.getUserIp();
} }
} else if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid.");
return;
} }
if (addedBy != null) { if (addedBy != null) {

View File

@ -15,6 +15,7 @@ import net.frozenorb.apiv3.actor.ActorType;
import net.frozenorb.apiv3.model.*; import net.frozenorb.apiv3.model.*;
import net.frozenorb.apiv3.unsorted.MongoToVertxCallback; import net.frozenorb.apiv3.unsorted.MongoToVertxCallback;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.PermissionUtils; import net.frozenorb.apiv3.util.PermissionUtils;
import net.frozenorb.apiv3.util.UuidUtils; import net.frozenorb.apiv3.util.UuidUtils;
@ -216,9 +217,10 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
players.forEach((entry) -> { players.forEach((entry) -> {
UUID uuid = UuidUtils.parseUuid(entry.getKey()); UUID uuid = UuidUtils.parseUuid(entry.getKey());
JsonObject data = (JsonObject) entry.getValue(); JsonObject data = (JsonObject) entry.getValue();
String userIp = data.getString("userIp");
if (UuidUtils.isAcceptableUuid(uuid)) { if (UuidUtils.isAcceptableUuid(uuid) && IpUtils.isValidIp(userIp)) {
result.put(uuid, data.getString("userIp")); result.put(uuid, userIp);
} }
}); });

View File

@ -7,6 +7,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog;
import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.auditLog.AuditLogActionType;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.UserSessionUtils; import net.frozenorb.apiv3.util.UserSessionUtils;
@ -41,6 +42,11 @@ public final class GETUsersIdVerifyPassword implements Handler<RoutingContext> {
boolean authorized = user.checkPassword(ctx.request().getParam("password")); boolean authorized = user.checkPassword(ctx.request().getParam("password"));
String userIp = ctx.request().getParam("userIp"); String userIp = ctx.request().getParam("userIp");
if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, authorized ? AuditLogActionType.USER_LOGIN_SUCCESS : AuditLogActionType.USER_LOGIN_FAIL, (ignored, error) -> { AuditLog.log(user.getId(), userIp, ctx, authorized ? AuditLogActionType.USER_LOGIN_SUCCESS : AuditLogActionType.USER_LOGIN_FAIL, (ignored, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);

View File

@ -10,10 +10,7 @@ import net.frozenorb.apiv3.auditLog.AuditLogActionType;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.RequiresTotpResult; import net.frozenorb.apiv3.unsorted.RequiresTotpResult;
import net.frozenorb.apiv3.unsorted.TotpAuthorizationResult; import net.frozenorb.apiv3.unsorted.TotpAuthorizationResult;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.*;
import net.frozenorb.apiv3.util.PasswordUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.UserSessionUtils;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -86,8 +83,14 @@ public final class POSTUsersIdChangePassword implements Handler<RoutingContext>
user.updatePassword(newPassword); user.updatePassword(newPassword);
SyncUtils.<Void>runBlocking(v -> user.save(v)); SyncUtils.<Void>runBlocking(v -> user.save(v));
SyncUtils.<Void>runBlocking(v -> UserSessionUtils.invalidateAllSessions(user.getId(), v)); SyncUtils.<Void>runBlocking(v -> UserSessionUtils.invalidateAllSessions(user.getId(), v));
String userIp = requestBody.getString("userIp");
AuditLog.log(user.getId(), requestBody.getString("userIp"), ctx, AuditLogActionType.USER_CHANGE_PASSWORD, (ignored, error) -> { if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, AuditLogActionType.USER_CHANGE_PASSWORD, (ignored, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {

View File

@ -9,6 +9,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog;
import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.auditLog.AuditLogActionType;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -61,8 +62,14 @@ public final class POSTUsersIdConfirmPhone implements Handler<RoutingContext> {
user.completePhoneRegistration(user.getPendingPhone()); user.completePhoneRegistration(user.getPendingPhone());
SyncUtils.<Void>runBlocking(v -> user.save(v)); SyncUtils.<Void>runBlocking(v -> user.save(v));
String userIp = requestBody.getString("userIp");
AuditLog.log(user.getId(), requestBody.getString("userIp"), ctx, AuditLogActionType.USER_CONFIRM_PHONE, (ignored, error) -> { if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, AuditLogActionType.USER_CONFIRM_PHONE, (ignored, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {

View File

@ -11,6 +11,7 @@ import net.frozenorb.apiv3.model.NotificationTemplate;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.Notification; import net.frozenorb.apiv3.unsorted.Notification;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
import java.util.Map; import java.util.Map;
@ -47,8 +48,14 @@ public final class POSTUsersIdPasswordReset implements Handler<RoutingContext> {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {
JsonObject requestBody = ctx.getBodyAsJson(); JsonObject requestBody = ctx.getBodyAsJson();
String userIp = requestBody.getString("userIp");
AuditLog.log(user.getId(), requestBody.getString("userIp"), ctx, AuditLogActionType.USER_PASSWORD_RESET, (ignored2, error2) -> { if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, AuditLogActionType.USER_PASSWORD_RESET, (ignored2, error2) -> {
if (error2 != null) { if (error2 != null) {
ErrorUtils.respondInternalError(ctx, error2); ErrorUtils.respondInternalError(ctx, error2);
} else { } else {

View File

@ -12,6 +12,7 @@ import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.Notification; import net.frozenorb.apiv3.unsorted.Notification;
import net.frozenorb.apiv3.util.EmailUtils; import net.frozenorb.apiv3.util.EmailUtils;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
import java.util.Map; import java.util.Map;
@ -73,7 +74,14 @@ public final class POSTUsersIdRegisterEmail implements Handler<RoutingContext> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {
AuditLog.log(user.getId(), requestBody.getString("userIp"), ctx, AuditLogActionType.USER_REGISTER_EMAIL, (ignored2, error2) -> { String userIp = requestBody.getString("userIp");
if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, AuditLogActionType.USER_REGISTER_EMAIL, (ignored2, error2) -> {
if (error2 != null) { if (error2 != null) {
ErrorUtils.respondInternalError(ctx, error2); ErrorUtils.respondInternalError(ctx, error2);
} else { } else {

View File

@ -13,6 +13,7 @@ import net.frozenorb.apiv3.model.PhoneIntel;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.Notification; import net.frozenorb.apiv3.unsorted.Notification;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.PhoneUtils; import net.frozenorb.apiv3.util.PhoneUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
@ -77,7 +78,14 @@ public final class POSTUsersIdRegisterPhone implements Handler<RoutingContext> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {
AuditLog.log(user.getId(), requestBody.getString("userIp"), ctx, AuditLogActionType.USER_REGISTER_PHONE, (ignored2, error2) -> { String userIp = requestBody.getString("userIp");
if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, AuditLogActionType.USER_REGISTER_PHONE, (ignored2, error2) -> {
if (error2 != null) { if (error2 != null) {
ErrorUtils.respondInternalError(ctx, error2); ErrorUtils.respondInternalError(ctx, error2);
} else { } else {

View File

@ -9,6 +9,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog;
import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.auditLog.AuditLogActionType;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.TotpUtils; import net.frozenorb.apiv3.util.TotpUtils;
@ -34,8 +35,14 @@ public final class POSTUsersIdSetupTotp implements Handler<RoutingContext> {
if (TotpUtils.authorizeUser(secret, totpCode)) { if (TotpUtils.authorizeUser(secret, totpCode)) {
user.setTotpSecret(secret); user.setTotpSecret(secret);
SyncUtils.<Void>runBlocking(v -> user.save(v)); SyncUtils.<Void>runBlocking(v -> user.save(v));
String userIp = requestBody.getString("userIp");
AuditLog.log(user.getId(), requestBody.getString("userIp"), ctx, AuditLogActionType.USER_SETUP_TOTP, (ignored, error) -> { if (!IpUtils.isValidIp(userIp)) {
ErrorUtils.respondInvalidInput(ctx, "Ip address \"" + userIp + "\" is not valid.");
return;
}
AuditLog.log(user.getId(), userIp, ctx, AuditLogActionType.USER_SETUP_TOTP, (ignored, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);
} else { } else {