From 746bce730e124a01716cc43a2145c54beca1883c Mon Sep 17 00:00:00 2001 From: Zaprit Date: Sat, 12 Oct 2024 16:42:57 +0100 Subject: [PATCH 1/6] feat: add config options to restrict signup on certain platforms --- .../Controllers/Login/LoginController.cs | 17 +++++++++++++++++ .../AuthenticationConfiguration.cs | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs index 7a4834634..b51da021e 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs @@ -130,6 +130,23 @@ public async Task Login() Logger.Warn($"Unknown user tried to connect username={username}", LogArea.Login); return this.Forbid(); } + + // Block RPCN signups if forbidden in config + if (npTicket.Platform == Platform.RPCS3 && !ServerConfiguration.Instance.Authentication.AllowRPCNSignup) + { + Logger.Warn( + $"New user tried to sign up via RPCN, and that is forbidden in the config, username={username}, remoteIpAddress={remoteIpAddress}", + LogArea.Login); + } + + // Block PSN signups if forbidden in config + if (npTicket.Platform == Platform.RPCS3 && !ServerConfiguration.Instance.Authentication.AllowPSNSignup) + { + Logger.Warn( + $"New user tried to sign up via PSN, and that is forbidden in the config, username={username}, remoteIpAddress={remoteIpAddress}", + LogArea.Login); + } + // create account for user if they don't exist user = await this.database.CreateUser(username, "$"); user.Password = null; diff --git a/ProjectLighthouse/Configuration/ConfigurationCategories/AuthenticationConfiguration.cs b/ProjectLighthouse/Configuration/ConfigurationCategories/AuthenticationConfiguration.cs index 76989aa2d..4c3abb368 100644 --- a/ProjectLighthouse/Configuration/ConfigurationCategories/AuthenticationConfiguration.cs +++ b/ProjectLighthouse/Configuration/ConfigurationCategories/AuthenticationConfiguration.cs @@ -5,4 +5,9 @@ public class AuthenticationConfiguration public bool RegistrationEnabled { get; set; } = true; public bool AutomaticAccountCreation { get; set; } = true; public bool VerifyTickets { get; set; } = true; + + public bool AllowRPCNSignup { get; set; } = true; + + public bool AllowPSNSignup { get; set; } = true; + } \ No newline at end of file From ce42909677b4e06ba302b863f05f89261f79a406 Mon Sep 17 00:00:00 2001 From: Zaprit Date: Sat, 12 Oct 2024 16:50:01 +0100 Subject: [PATCH 2/6] add isPSN extension to platform enum --- ProjectLighthouse/Types/Users/Platform.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ProjectLighthouse/Types/Users/Platform.cs b/ProjectLighthouse/Types/Users/Platform.cs index d30ba1592..3e5811b0e 100644 --- a/ProjectLighthouse/Types/Users/Platform.cs +++ b/ProjectLighthouse/Types/Users/Platform.cs @@ -1,5 +1,14 @@ namespace LBPUnion.ProjectLighthouse.Types.Users; +public static class PlatformExtensions +{ + + public static bool IsPSN(this Platform platform) + { + return platform == Platform.PS3 || platform == Platform.PSP || platform == Platform.Vita; + } +} + public enum Platform { PS3 = 0, From b026da3bad89b76fb4cb33d7b2bcca674379ba53 Mon Sep 17 00:00:00 2001 From: Zaprit Date: Sat, 12 Oct 2024 16:51:27 +0100 Subject: [PATCH 3/6] actually forbid on invalid sign-up attempt, and fix compiler warnings --- .../Controllers/Login/LoginController.cs | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs index b51da021e..43fe553e4 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs @@ -1,4 +1,3 @@ -#nullable enable using System.Net; using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Database; @@ -18,15 +17,8 @@ namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Login; [ApiController] [Route("LITTLEBIGPLANETPS3_XML/login")] [Produces("text/xml")] -public class LoginController : ControllerBase +public class LoginController(DatabaseContext database) : ControllerBase { - private readonly DatabaseContext database; - - public LoginController(DatabaseContext database) - { - this.database = database; - } - [HttpPost] public async Task Login() { @@ -57,27 +49,27 @@ public async Task Login() string ipAddress = remoteIpAddress.ToString(); - string? username = npTicket.Username; + string username = npTicket.Username; - if (username == null) + if (String.IsNullOrEmpty(username)) { Logger.Warn("Unable to determine username, rejecting login", LogArea.Login); return this.Forbid(); } - await this.database.RemoveExpiredTokens(); + await database.RemoveExpiredTokens(); UserEntity? user; switch (npTicket.Platform) { case Platform.RPCS3: - user = await this.database.Users.FirstOrDefaultAsync(u => u.LinkedRpcnId == npTicket.UserId); + user = await database.Users.FirstOrDefaultAsync(u => u.LinkedRpcnId == npTicket.UserId); break; case Platform.PS3: case Platform.Vita: case Platform.UnitTest: - user = await this.database.Users.FirstOrDefaultAsync(u => u.LinkedPsnId == npTicket.UserId); + user = await database.Users.FirstOrDefaultAsync(u => u.LinkedPsnId == npTicket.UserId); break; case Platform.PSP: case Platform.Unknown: @@ -89,7 +81,7 @@ public async Task Login() if (user == null) { // Check if there is an account with that username already - UserEntity? targetUsername = await this.database.Users.FirstOrDefaultAsync(u => u.Username == npTicket.Username); + UserEntity? targetUsername = await database.Users.FirstOrDefaultAsync(u => u.Username == npTicket.Username); if (targetUsername != null) { ulong targetPlatform = npTicket.Platform == Platform.RPCS3 @@ -104,7 +96,7 @@ public async Task Login() } // if there is already a pending link request don't create another - bool linkAttemptExists = await this.database.PlatformLinkAttempts.AnyAsync(p => + bool linkAttemptExists = await database.PlatformLinkAttempts.AnyAsync(p => p.Platform == npTicket.Platform && p.PlatformId == npTicket.UserId && p.UserId == targetUsername.UserId); @@ -119,8 +111,8 @@ public async Task Login() Timestamp = TimeHelper.TimestampMillis, PlatformId = npTicket.UserId, }; - this.database.PlatformLinkAttempts.Add(linkAttempt); - await this.database.SaveChangesAsync(); + database.PlatformLinkAttempts.Add(linkAttempt); + await database.SaveChangesAsync(); Logger.Success($"User '{npTicket.Username}' tried to login but platform isn't linked, platform={npTicket.Platform}", LogArea.Login); return this.Forbid(); } @@ -137,22 +129,24 @@ public async Task Login() Logger.Warn( $"New user tried to sign up via RPCN, and that is forbidden in the config, username={username}, remoteIpAddress={remoteIpAddress}", LogArea.Login); + return this.Forbid(); } // Block PSN signups if forbidden in config - if (npTicket.Platform == Platform.RPCS3 && !ServerConfiguration.Instance.Authentication.AllowPSNSignup) + if (npTicket.Platform.IsPSN() && !ServerConfiguration.Instance.Authentication.AllowPSNSignup) { Logger.Warn( $"New user tried to sign up via PSN, and that is forbidden in the config, username={username}, remoteIpAddress={remoteIpAddress}", LogArea.Login); + return this.Forbid(); } // create account for user if they don't exist - user = await this.database.CreateUser(username, "$"); + user = await database.CreateUser(username, "$"); user.Password = null; user.LinkedRpcnId = npTicket.Platform == Platform.RPCS3 ? npTicket.UserId : 0; user.LinkedPsnId = npTicket.Platform != Platform.RPCS3 ? npTicket.UserId : 0; - await this.database.SaveChangesAsync(); + await database.SaveChangesAsync(); if (DiscordConfiguration.Instance.DiscordIntegrationEnabled) { @@ -172,7 +166,7 @@ public async Task Login() // automatically change username if it doesn't match else if (user.Username != npTicket.Username) { - bool usernameExists = await this.database.Users.AnyAsync(u => u.Username == npTicket.Username); + bool usernameExists = await database.Users.AnyAsync(u => u.Username == npTicket.Username); if (usernameExists) { Logger.Warn($"{npTicket.Platform} user changed their name to a name that is already taken," + @@ -181,17 +175,17 @@ public async Task Login() } Logger.Info($"User's username has changed, old='{user.Username}', new='{npTicket.Username}', platform={npTicket.Platform}", LogArea.Login); user.Username = username; - await this.database.PlatformLinkAttempts.RemoveWhere(p => p.UserId == user.UserId); + await database.PlatformLinkAttempts.RemoveWhere(p => p.UserId == user.UserId); // unlink other platforms because the names no longer match if (npTicket.Platform == Platform.RPCS3) user.LinkedPsnId = 0; else user.LinkedRpcnId = 0; - await this.database.SaveChangesAsync(); + await database.SaveChangesAsync(); } - GameTokenEntity? token = await this.database.GameTokens.Include(t => t.User) + GameTokenEntity? token = await database.GameTokens.Include(t => t.User) .FirstOrDefaultAsync(t => t.User.Username == npTicket.Username && t.TicketHash == npTicket.TicketHash); if (token != null) @@ -200,7 +194,7 @@ public async Task Login() return this.Forbid(); } - token = await this.database.AuthenticateUser(user, npTicket, ipAddress); + token = await database.AuthenticateUser(user, npTicket, ipAddress); if (token == null) { Logger.Warn($"Unable to find/generate a token for username {npTicket.Username}", LogArea.Login); @@ -217,7 +211,7 @@ public async Task Login() user.LastLogin = TimeHelper.TimestampMillis; - await this.database.SaveChangesAsync(); + await database.SaveChangesAsync(); // Create a new room on LBP2/3/Vita if (token.GameVersion != GameVersion.LittleBigPlanet1) RoomHelper.CreateRoom(user.UserId, token.GameVersion, token.Platform); From d34e6a7b1cd4bf5b044b274ec5ddd80b7b24cfc8 Mon Sep 17 00:00:00 2001 From: Zaprit Date: Sun, 20 Oct 2024 17:32:04 +0100 Subject: [PATCH 4/6] Fix code review suggestions --- .../Controllers/Login/LoginController.cs | 12 +++++++++--- .../Configuration/ServerConfiguration.cs | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs index 43fe553e4..082a560ea 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs @@ -17,8 +17,14 @@ namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Login; [ApiController] [Route("LITTLEBIGPLANETPS3_XML/login")] [Produces("text/xml")] -public class LoginController(DatabaseContext database) : ControllerBase +public class LoginController : ControllerBase { + private readonly DatabaseContext database; + public LoginController(DatabaseContext database) + { + this.database = database; + } + [HttpPost] public async Task Login() { @@ -51,13 +57,13 @@ public async Task Login() string username = npTicket.Username; - if (String.IsNullOrEmpty(username)) + if (string.IsNullOrEmpty(username)) { Logger.Warn("Unable to determine username, rejecting login", LogArea.Login); return this.Forbid(); } - await database.RemoveExpiredTokens(); + await this.database.RemoveExpiredTokens(); UserEntity? user; diff --git a/ProjectLighthouse/Configuration/ServerConfiguration.cs b/ProjectLighthouse/Configuration/ServerConfiguration.cs index 30c7c89be..ba9f7f4a1 100644 --- a/ProjectLighthouse/Configuration/ServerConfiguration.cs +++ b/ProjectLighthouse/Configuration/ServerConfiguration.cs @@ -11,7 +11,7 @@ public class ServerConfiguration : ConfigurationBase // This is so Lighthouse can properly identify outdated configurations and update them with newer settings accordingly. // If you are modifying anything here, this value MUST be incremented. // Thanks for listening~ - public override int ConfigVersion { get; set; } = 26; + public override int ConfigVersion { get; set; } = 27; public override string ConfigName { get; set; } = "lighthouse.yml"; public string WebsiteListenUrl { get; set; } = "http://localhost:10060"; From 1e598d49bb9d1f07246a8c3fd1aef1e243a6ff02 Mon Sep 17 00:00:00 2001 From: Henry Asbridge Date: Sat, 2 Nov 2024 11:30:48 +0000 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Josh --- .../Controllers/Login/LoginController.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs index 082a560ea..077f1b006 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Login/LoginController.cs @@ -24,7 +24,6 @@ public LoginController(DatabaseContext database) { this.database = database; } - [HttpPost] public async Task Login() { @@ -70,7 +69,7 @@ public async Task Login() switch (npTicket.Platform) { case Platform.RPCS3: - user = await database.Users.FirstOrDefaultAsync(u => u.LinkedRpcnId == npTicket.UserId); + user = await this.database.Users.FirstOrDefaultAsync(u => u.LinkedRpcnId == npTicket.UserId); break; case Platform.PS3: case Platform.Vita: From 9e742e881453cc8107ef227c1d30d6422f5c2cf4 Mon Sep 17 00:00:00 2001 From: Zaprit Date: Sat, 2 Nov 2024 11:58:04 +0000 Subject: [PATCH 6/6] Fix qodana pipeline --- .github/workflows/qodana_code_quality.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index 6c20246ce..b3df742ba 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -1,7 +1,9 @@ name: Qodana on: workflow_dispatch: - pull_request: + pull_request_target: + branches: + - main push: branches: # Specify your branches here - main # The 'main' branch @@ -25,4 +27,7 @@ jobs: pr-mode: false env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1488465344 }} - QODANA_ENDPOINT: 'https://qodana.cloud' \ No newline at end of file + QODANA_ENDPOINT: 'https://qodana.cloud' + - uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: ${{ runner.temp }}/qodana/results/qodana.sarif.json