|
4 | 4 | using ReactiveUI; |
5 | 5 | using System; |
6 | 6 | using System.Linq; |
| 7 | +using System.Net; |
7 | 8 | using System.Reactive; |
8 | 9 | using System.Reactive.Linq; |
9 | 10 | using System.Threading.Tasks; |
@@ -91,20 +92,13 @@ private async Task ConnectAsync() |
91 | 92 |
|
92 | 93 | if (infoLogin is LoginSuccessful success) |
93 | 94 | { |
94 | | - int playerCount = session.Players.AllPlayers.Count(p => !p.IsGroup); |
95 | 95 | string game = session.Players.ActivePlayer.Game; |
96 | | - bool isRaceMode = session.DataStorage.GetRaceMode(); |
| 96 | + string? guardRailError = await GetGuardRailErrorMessage(session); |
97 | 97 | await session.Socket.DisconnectAsync(); |
98 | 98 |
|
99 | | - // always includes player for server |
100 | | - if (playerCount > 3) |
| 99 | + if (guardRailError != null) |
101 | 100 | { |
102 | | - ErrorMessage = "Debug client only supports connecting to games with 2 or fewer players to prevent abuse"; |
103 | | - return; |
104 | | - } |
105 | | - if (isRaceMode) |
106 | | - { |
107 | | - ErrorMessage = "Debug client cannot be used in race mode to prevent abuse"; |
| 101 | + ErrorMessage = guardRailError; |
108 | 102 | return; |
109 | 103 | } |
110 | 104 |
|
@@ -148,6 +142,40 @@ private async Task<LoginResult> TryConnectAndLoginAsync(ArchipelagoSession sessi |
148 | 142 | new Version(0, 5, 0), tags: tags, password: password, requestSlotData: false); |
149 | 143 | } |
150 | 144 |
|
| 145 | + private async Task<string?> GetGuardRailErrorMessage(IArchipelagoSession session) |
| 146 | + { |
| 147 | + // games on localhost are always safe - malevolent hosts can already use admin console here |
| 148 | + // if they want to grief |
| 149 | + string trimmedAddress = Address; |
| 150 | + if (trimmedAddress.Split("://") is [_, string hostPort]) |
| 151 | + { |
| 152 | + trimmedAddress = hostPort; |
| 153 | + } |
| 154 | + if (trimmedAddress.Split(":") is [string hostname, ..]) |
| 155 | + { |
| 156 | + trimmedAddress = hostname; |
| 157 | + } |
| 158 | + IPHostEntry hostEntry = await Dns.GetHostEntryAsync(trimmedAddress); |
| 159 | + if (hostEntry.AddressList.Any(addr => addr.Equals(IPAddress.Loopback) || addr.Equals(IPAddress.IPv6Loopback))) |
| 160 | + { |
| 161 | + return null; |
| 162 | + } |
| 163 | + |
| 164 | + int playerCount = session.Players.AllPlayers.Count(p => !p.IsGroup); |
| 165 | + bool isRaceMode = session.DataStorage.GetRaceMode(); |
| 166 | + |
| 167 | + // always includes player for server |
| 168 | + if (playerCount > 3) |
| 169 | + { |
| 170 | + return "Debug client only supports connecting to non-local games with 2 or fewer players to prevent abuse"; |
| 171 | + } |
| 172 | + if (isRaceMode) |
| 173 | + { |
| 174 | + return "Debug client cannot be used in race mode to prevent abuse"; |
| 175 | + } |
| 176 | + return null; |
| 177 | + } |
| 178 | + |
151 | 179 | private string BuildErrorForFailedLogin(LoginFailure failure) |
152 | 180 | { |
153 | 181 | string errors = string.Join(", ", failure.Errors); |
|
0 commit comments