From 4b0d66985e8336de555c25cab2c3db301b55e414 Mon Sep 17 00:00:00 2001 From: Colin McDonald Date: Mon, 25 Jul 2016 20:58:52 -0400 Subject: [PATCH] Add ip validations where needed --- pom.xml | 10 ++++---- src/main/java/net/frozenorb/apiv3/APIv3.java | 24 +++++++++++++++++++ .../handler/WebsiteUserSessionHandler.java | 6 +++++ .../emailTokens/POSTEmailTokensIdConfirm.java | 9 ++++++- .../apiv3/route/ipBans/GETIpBans.java | 9 ++++++- .../route/punishments/POSTPunishments.java | 4 ++++ .../route/servers/POSTServersHeartbeat.java | 6 +++-- .../route/users/GETUsersIdVerifyPassword.java | 6 +++++ .../users/POSTUsersIdChangePassword.java | 13 ++++++---- .../route/users/POSTUsersIdConfirmPhone.java | 9 ++++++- .../route/users/POSTUsersIdPasswordReset.java | 9 ++++++- .../route/users/POSTUsersIdRegisterEmail.java | 10 +++++++- .../route/users/POSTUsersIdRegisterPhone.java | 10 +++++++- .../route/users/POSTUsersIdSetupTotp.java | 9 ++++++- 14 files changed, 115 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index e01b5ab..0940f09 100644 --- a/pom.xml +++ b/pom.xml @@ -67,27 +67,27 @@ io.vertx vertx-core - 3.3.1 + 3.3.2 io.vertx vertx-web - 3.3.1 + 3.3.2 io.vertx vertx-redis-client - 3.3.1 + 3.3.2 io.vertx vertx-circuit-breaker - 3.3.1 + 3.3.2 io.vertx vertx-dropwizard-metrics - 3.3.1 + 3.3.2 diff --git a/src/main/java/net/frozenorb/apiv3/APIv3.java b/src/main/java/net/frozenorb/apiv3/APIv3.java index 7774d73..04404b7 100644 --- a/src/main/java/net/frozenorb/apiv3/APIv3.java +++ b/src/main/java/net/frozenorb/apiv3/APIv3.java @@ -105,6 +105,7 @@ import net.frozenorb.apiv3.serialization.mongodb.UuidCodecProvider; import net.frozenorb.apiv3.util.EmailUtils; import net.frozenorb.apiv3.util.MojangUtils; import net.frozenorb.apiv3.util.SyncUtils; +import net.frozenorb.apiv3.util.UserSessionUtils; import org.bson.Document; import org.bson.codecs.BsonValueCodecProvider; import org.bson.codecs.DocumentCodecProvider; @@ -139,6 +140,29 @@ public final class APIv3 extends AbstractVerticle { setupMetrics(); 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) -> { if (error != null) { error.printStackTrace(); diff --git a/src/main/java/net/frozenorb/apiv3/handler/WebsiteUserSessionHandler.java b/src/main/java/net/frozenorb/apiv3/handler/WebsiteUserSessionHandler.java index 0961f20..a377010 100644 --- a/src/main/java/net/frozenorb/apiv3/handler/WebsiteUserSessionHandler.java +++ b/src/main/java/net/frozenorb/apiv3/handler/WebsiteUserSessionHandler.java @@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j; import net.frozenorb.apiv3.actor.Actor; import net.frozenorb.apiv3.actor.ActorType; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.UserSessionUtils; @Slf4j @@ -30,6 +31,11 @@ public final class WebsiteUserSessionHandler implements Handler String userSession = ctx.request().getHeader("MHQ-UserSession"); 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) -> { if (error != null) { ErrorUtils.respondInternalError(ctx, error); diff --git a/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java b/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java index 81630a6..e2653ab 100644 --- a/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java +++ b/src/main/java/net/frozenorb/apiv3/route/emailTokens/POSTEmailTokensIdConfirm.java @@ -9,6 +9,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog; import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.PasswordUtils; import net.frozenorb.apiv3.util.SyncUtils; @@ -57,8 +58,14 @@ public final class POSTEmailTokensIdConfirm implements Handler { user.completeEmailRegistration(user.getPendingEmail()); user.updatePassword(password); SyncUtils.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) { ErrorUtils.respondInternalError(ctx, error); } else { diff --git a/src/main/java/net/frozenorb/apiv3/route/ipBans/GETIpBans.java b/src/main/java/net/frozenorb/apiv3/route/ipBans/GETIpBans.java index 4a72242..155f433 100644 --- a/src/main/java/net/frozenorb/apiv3/route/ipBans/GETIpBans.java +++ b/src/main/java/net/frozenorb/apiv3/route/ipBans/GETIpBans.java @@ -5,6 +5,7 @@ import io.vertx.ext.web.RoutingContext; import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.model.IpBan; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.UuidUtils; import org.bson.Document; @@ -14,8 +15,14 @@ public final class GETIpBans implements Handler { try { 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")); + 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) { ErrorUtils.respondInternalError(ctx, error); } else { diff --git a/src/main/java/net/frozenorb/apiv3/route/punishments/POSTPunishments.java b/src/main/java/net/frozenorb/apiv3/route/punishments/POSTPunishments.java index 2ef8277..29a7532 100644 --- a/src/main/java/net/frozenorb/apiv3/route/punishments/POSTPunishments.java +++ b/src/main/java/net/frozenorb/apiv3/route/punishments/POSTPunishments.java @@ -14,6 +14,7 @@ import net.frozenorb.apiv3.model.Punishment; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.unsorted.Permissions; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.SyncUtils; import java.time.Instant; @@ -96,6 +97,9 @@ public final class POSTPunishments implements Handler { if (latestIpLogEntry != null) { userIp = latestIpLogEntry.getUserIp(); } + } else if (!IpUtils.isValidIp(userIp)) { + ErrorUtils.respondInvalidInput(ctx, "IP address \"" + userIp + "\" is not valid."); + return; } if (addedBy != null) { diff --git a/src/main/java/net/frozenorb/apiv3/route/servers/POSTServersHeartbeat.java b/src/main/java/net/frozenorb/apiv3/route/servers/POSTServersHeartbeat.java index d003da0..07bc060 100644 --- a/src/main/java/net/frozenorb/apiv3/route/servers/POSTServersHeartbeat.java +++ b/src/main/java/net/frozenorb/apiv3/route/servers/POSTServersHeartbeat.java @@ -15,6 +15,7 @@ import net.frozenorb.apiv3.actor.ActorType; import net.frozenorb.apiv3.model.*; import net.frozenorb.apiv3.unsorted.MongoToVertxCallback; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.PermissionUtils; import net.frozenorb.apiv3.util.UuidUtils; @@ -216,9 +217,10 @@ public final class POSTServersHeartbeat implements Handler { players.forEach((entry) -> { UUID uuid = UuidUtils.parseUuid(entry.getKey()); JsonObject data = (JsonObject) entry.getValue(); + String userIp = data.getString("userIp"); - if (UuidUtils.isAcceptableUuid(uuid)) { - result.put(uuid, data.getString("userIp")); + if (UuidUtils.isAcceptableUuid(uuid) && IpUtils.isValidIp(userIp)) { + result.put(uuid, userIp); } }); diff --git a/src/main/java/net/frozenorb/apiv3/route/users/GETUsersIdVerifyPassword.java b/src/main/java/net/frozenorb/apiv3/route/users/GETUsersIdVerifyPassword.java index aac2de8..cf06d76 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/GETUsersIdVerifyPassword.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/GETUsersIdVerifyPassword.java @@ -7,6 +7,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog; import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.UserSessionUtils; @@ -41,6 +42,11 @@ public final class GETUsersIdVerifyPassword implements Handler { boolean authorized = user.checkPassword(ctx.request().getParam("password")); 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) -> { if (error != null) { ErrorUtils.respondInternalError(ctx, error); diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java index 19fe184..3366d12 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdChangePassword.java @@ -10,10 +10,7 @@ import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.unsorted.RequiresTotpResult; import net.frozenorb.apiv3.unsorted.TotpAuthorizationResult; -import net.frozenorb.apiv3.util.ErrorUtils; -import net.frozenorb.apiv3.util.PasswordUtils; -import net.frozenorb.apiv3.util.SyncUtils; -import net.frozenorb.apiv3.util.UserSessionUtils; +import net.frozenorb.apiv3.util.*; import java.util.concurrent.TimeUnit; @@ -86,8 +83,14 @@ public final class POSTUsersIdChangePassword implements Handler user.updatePassword(newPassword); SyncUtils.runBlocking(v -> user.save(v)); SyncUtils.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) { ErrorUtils.respondInternalError(ctx, error); } else { diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdConfirmPhone.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdConfirmPhone.java index 8d3b26c..7268cf0 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdConfirmPhone.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdConfirmPhone.java @@ -9,6 +9,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog; import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.SyncUtils; import java.util.concurrent.TimeUnit; @@ -61,8 +62,14 @@ public final class POSTUsersIdConfirmPhone implements Handler { user.completePhoneRegistration(user.getPendingPhone()); SyncUtils.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) { ErrorUtils.respondInternalError(ctx, error); } else { diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdPasswordReset.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdPasswordReset.java index 8bf8f0d..9b52c0d 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdPasswordReset.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdPasswordReset.java @@ -11,6 +11,7 @@ import net.frozenorb.apiv3.model.NotificationTemplate; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.unsorted.Notification; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.SyncUtils; import java.util.Map; @@ -47,8 +48,14 @@ public final class POSTUsersIdPasswordReset implements Handler { ErrorUtils.respondInternalError(ctx, error); } else { 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) { ErrorUtils.respondInternalError(ctx, error2); } else { diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java index 2de0ed1..1462df1 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterEmail.java @@ -12,6 +12,7 @@ import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.unsorted.Notification; import net.frozenorb.apiv3.util.EmailUtils; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.SyncUtils; import java.util.Map; @@ -73,7 +74,14 @@ public final class POSTUsersIdRegisterEmail implements Handler { if (error != null) { ErrorUtils.respondInternalError(ctx, error); } 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) { ErrorUtils.respondInternalError(ctx, error2); } else { diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java index 50ff1e6..347f468 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdRegisterPhone.java @@ -13,6 +13,7 @@ import net.frozenorb.apiv3.model.PhoneIntel; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.unsorted.Notification; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.PhoneUtils; import net.frozenorb.apiv3.util.SyncUtils; @@ -77,7 +78,14 @@ public final class POSTUsersIdRegisterPhone implements Handler { if (error != null) { ErrorUtils.respondInternalError(ctx, error); } 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) { ErrorUtils.respondInternalError(ctx, error2); } else { diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdSetupTotp.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdSetupTotp.java index 1f5bd12..cd35edd 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdSetupTotp.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUsersIdSetupTotp.java @@ -9,6 +9,7 @@ import net.frozenorb.apiv3.auditLog.AuditLog; import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.util.ErrorUtils; +import net.frozenorb.apiv3.util.IpUtils; import net.frozenorb.apiv3.util.SyncUtils; import net.frozenorb.apiv3.util.TotpUtils; @@ -34,8 +35,14 @@ public final class POSTUsersIdSetupTotp implements Handler { if (TotpUtils.authorizeUser(secret, totpCode)) { user.setTotpSecret(secret); SyncUtils.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) { ErrorUtils.respondInternalError(ctx, error); } else {