-
Notifications
You must be signed in to change notification settings - Fork 108
MCL-19983 & WEB-1429 Fixed legacy skin loading & server authentication. #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
craftycodie
wants to merge
8
commits into
Mojang:master
Choose a base branch
from
craftycodie:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+421
−3
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3105a19
MCL-19983 Fixed legacy skin loading.
craftycodie bd7172e
A little refactoring.
craftycodie bcd7ea4
Updated log4j
craftycodie b011d88
Removed reference to internal `HttpURLConnection`
craftycodie afdcc29
Corrected skin adjustments (thanks @DelofJ)
craftycodie 8e4d5ad
Added online-mode fix.
craftycodie 76f25d5
Merge pull request #2 from craftycodie/feature/online-mode
craftycodie 834a4a5
Version Bump
craftycodie File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
src/main/java/net/minecraft/launchwrapper/protocol/CapeURLConnection.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| package net.minecraft.launchwrapper.protocol; | ||
|
|
||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.net.HttpURLConnection; | ||
| import java.net.URL; | ||
| import java.util.Map; | ||
| import java.net.Proxy; | ||
|
|
||
| import com.mojang.authlib.minecraft.MinecraftProfileTexture; | ||
| import com.mojang.authlib.ProfileLookupCallback; | ||
| import com.mojang.authlib.GameProfile; | ||
| import com.mojang.authlib.Agent; | ||
| import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; | ||
|
|
||
| public class CapeURLConnection extends HttpURLConnection { | ||
|
|
||
| public final static String[] OLD_CAPE_ADDRESSES = new String[] { | ||
| "http://www.minecraft.net/cloak/get.jsp?user=", // Introduced Beta 1.0 (when capes were added) | ||
| "http://s3.amazonaws.com/MinecraftCloaks/", // Introduced Beta 1.2 | ||
| "http://skins.minecraft.net/MinecraftCloaks/" // Introduced Release 1.3.1 | ||
| }; | ||
|
|
||
| public CapeURLConnection(URL url) { | ||
| super(url); | ||
| } | ||
|
|
||
| @Override | ||
| public void disconnect() { | ||
| } | ||
|
|
||
| @Override | ||
| public boolean usingProxy() { | ||
| return false; | ||
| } | ||
|
|
||
| InputStream inputStream = null; | ||
| int responseCode = 200; | ||
|
|
||
| private String getUsernameFromURL() { | ||
| String username = this.url.toString(); | ||
|
|
||
| // We get the username from the skin by replacing the url up to the username with whitespace. | ||
| for (String oldCapeAddress : OLD_CAPE_ADDRESSES) { | ||
| username = username.replace(oldCapeAddress, ""); | ||
| } | ||
| /// ... and dropping the .png. | ||
| username = username.replace(".png", ""); | ||
|
|
||
| return username; | ||
| } | ||
|
|
||
| @Override | ||
| public void connect() throws IOException { | ||
| String username = getUsernameFromURL(); | ||
|
|
||
| try { | ||
| MinecraftProfileTexture cape = getUserCape(username); | ||
| inputStream = new URL(cape.getUrl()).openConnection().getInputStream(); | ||
| } catch (Exception ex) { | ||
| responseCode = 404; | ||
| } | ||
| } | ||
|
|
||
| YggdrasilAuthenticationService authenticationService = new YggdrasilAuthenticationService(Proxy.NO_PROXY, (String)null); | ||
| GameProfile gameProfile = null; | ||
|
|
||
| private MinecraftProfileTexture getUserCape(String username) { | ||
| authenticationService.createProfileRepository().findProfilesByNames(new String[] { username }, Agent.MINECRAFT, new ProfileLookupCallback() { | ||
| public void onProfileLookupSucceeded(GameProfile paramGameProfile) { | ||
| gameProfile = paramGameProfile; | ||
| } | ||
| public void onProfileLookupFailed(GameProfile paramGameProfile, Exception paramException) { | ||
| } | ||
| }); | ||
|
|
||
| if (gameProfile == null) | ||
| return null; | ||
|
|
||
| gameProfile = authenticationService.createMinecraftSessionService().fillProfileProperties(gameProfile, true); | ||
|
|
||
| Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures = authenticationService.createMinecraftSessionService().getTextures(gameProfile, true); | ||
| if (textures.containsKey(MinecraftProfileTexture.Type.CAPE)) | ||
| return textures.get(MinecraftProfileTexture.Type.CAPE); | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public InputStream getInputStream() throws IOException { | ||
| return inputStream; | ||
| } | ||
|
|
||
| @Override | ||
| public int getResponseCode() { | ||
| return responseCode; | ||
| } | ||
| } |
98 changes: 98 additions & 0 deletions
98
src/main/java/net/minecraft/launchwrapper/protocol/JoinServerURLConnection.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| package net.minecraft.launchwrapper.protocol; | ||
|
|
||
| import java.io.ByteArrayInputStream; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.net.HttpURLConnection; | ||
| import java.net.URL; | ||
| import java.net.Proxy; | ||
| import java.util.Map; | ||
| import java.util.HashMap; | ||
|
|
||
| import com.mojang.authlib.ProfileLookupCallback; | ||
| import com.mojang.authlib.GameProfile; | ||
| import com.mojang.authlib.Agent; | ||
| import com.mojang.authlib.exceptions.AuthenticationException; | ||
| import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; | ||
|
|
||
| public class JoinServerURLConnection extends HttpURLConnection { | ||
| public JoinServerURLConnection(URL url) { | ||
| super(url); | ||
| } | ||
|
|
||
| @Override | ||
| public void disconnect() { | ||
|
|
||
| } | ||
|
|
||
| @Override | ||
| public boolean usingProxy() { | ||
| return false; | ||
| } | ||
|
|
||
| private String response = "bad login"; | ||
|
|
||
| @Override | ||
| public void connect() throws IOException { | ||
|
|
||
| } | ||
|
|
||
| YggdrasilAuthenticationService authenticationService = new YggdrasilAuthenticationService(Proxy.NO_PROXY, (String)null); | ||
|
|
||
| GameProfile gameProfile = null; | ||
|
|
||
| @Override | ||
| public InputStream getInputStream() throws IOException { | ||
| // Pull params from the URL query. | ||
| String[] params = this.url.getQuery().split("&"); | ||
| Map<String, String> queryMap = new HashMap<String, String>(); | ||
|
|
||
| for (String param : params) { | ||
| String name = param.split("=")[0]; | ||
| String value = param.split("=")[1]; | ||
| queryMap.put(name, value); | ||
| } | ||
|
|
||
| String username = queryMap.get("user"); | ||
| // sessionId is token:<accessToken>:<playerId>. We want the access token. | ||
| String accessToken = queryMap.get("sessionId").split(":")[1]; | ||
| String serverId = queryMap.get("serverId"); | ||
|
|
||
| // Lookup the game profile by username. | ||
| authenticationService.createProfileRepository().findProfilesByNames(new String[] { username }, Agent.MINECRAFT, new ProfileLookupCallback() { | ||
| public void onProfileLookupSucceeded(GameProfile paramGameProfile) { | ||
| gameProfile = paramGameProfile; | ||
| } | ||
| public void onProfileLookupFailed(GameProfile paramGameProfile, Exception paramException) { | ||
| } | ||
| }); | ||
|
|
||
| if (gameProfile == null) | ||
| return null; | ||
|
|
||
| // Send the join request. | ||
| try { | ||
| authenticationService.createMinecraftSessionService().joinServer( | ||
| gameProfile, | ||
| accessToken, | ||
| serverId | ||
| ); | ||
|
|
||
| response = "ok"; | ||
| } catch (AuthenticationException ex) { | ||
| // response defaults to "bad login" | ||
| } | ||
|
|
||
| return new ByteArrayInputStream(response.getBytes()); | ||
| } | ||
|
|
||
| @Override | ||
| public int getResponseCode() { | ||
| return 200; | ||
| } | ||
|
|
||
| @Override | ||
| public String getResponseMessage() { | ||
| return "ok"; | ||
| } | ||
| } |
42 changes: 42 additions & 0 deletions
42
src/main/java/net/minecraft/launchwrapper/protocol/LegacyProtocolURLStreamHandler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package net.minecraft.launchwrapper.protocol; | ||
|
|
||
| import java.io.IOException; | ||
| import java.net.URL; | ||
| import java.net.Proxy; | ||
| import java.net.URLConnection; | ||
| import java.net.URLStreamHandler; | ||
|
|
||
| public class LegacyProtocolURLStreamHandler extends URLStreamHandler { | ||
| private final Class<? extends URLConnection> defaultHttpConnectionClass; | ||
|
|
||
| public LegacyProtocolURLStreamHandler(Class<? extends URLConnection> _defaultHttpConnectionClass) { | ||
| defaultHttpConnectionClass = _defaultHttpConnectionClass; | ||
| } | ||
|
|
||
| @Override | ||
| protected URLConnection openConnection(URL url) throws IOException { | ||
| // Skins are pulled from the new endpoint and converted to the legacy format as required. | ||
| for (String oldSkinAddress : SkinURLConnection.OLD_SKIN_ADDRESSES) { | ||
| if (url.toString().startsWith(oldSkinAddress)) | ||
| return new SkinURLConnection(url); | ||
| } | ||
|
|
||
| // Capes are pulled from the new endpoint, no conversion is required. | ||
| for (String oldCapeAddress : CapeURLConnection.OLD_CAPE_ADDRESSES) { | ||
| if (url.toString().startsWith(oldCapeAddress)) | ||
| return new CapeURLConnection(url); | ||
| } | ||
|
|
||
| // Server authentication is done over a newer endpoint. | ||
| if (url.toString().startsWith("http://www.minecraft.net/game/joinserver.jsp")) { | ||
| return new JoinServerURLConnection(url); | ||
| } | ||
|
|
||
| try { | ||
| return defaultHttpConnectionClass.getConstructor(URL.class, Proxy.class).newInstance(url, Proxy.NO_PROXY); | ||
| } catch (Exception e) { | ||
| // If the constructor isn't found, you can log that out. It's not expected. | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
30 changes: 30 additions & 0 deletions
30
...main/java/net/minecraft/launchwrapper/protocol/LegacyProtocolURLStreamHandlerFactory.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package net.minecraft.launchwrapper.protocol; | ||
|
|
||
| import java.net.URL; | ||
| import java.net.URLConnection; | ||
| import java.net.URLStreamHandler; | ||
| import java.net.URLStreamHandlerFactory; | ||
|
|
||
| public class LegacyProtocolURLStreamHandlerFactory implements URLStreamHandlerFactory { | ||
| private final Class<? extends URLConnection> defaultHttpConnectionClass; | ||
|
|
||
| public LegacyProtocolURLStreamHandlerFactory() { | ||
| try { | ||
| URL foo = new URL("http://example.com"); | ||
| // Doesn't actually establish a connection | ||
| defaultHttpConnectionClass = foo.openConnection().getClass(); | ||
| } catch (Exception e) { | ||
| // this should never happen as the URL is hardcoded, shouldn't be invalid. | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public URLStreamHandler createURLStreamHandler(String protocol) { | ||
| if ("http".equals(protocol)) { | ||
| return new LegacyProtocolURLStreamHandler(defaultHttpConnectionClass); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To add additional safety features for Beta 1.8+, this should not only support "www.minecraft.net", but also (the still working, but terrible security wise) "session.minecraft.net". Besides the different subdomain, rest of the URL is the same (and the difference doesn't matter later on, see: JoinServerURLConnection#getInputStream).
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you explain this conclusion?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as with "www.minecraft.net":
Again, the only difference between "www.minecraft.net" and "session.minecraft.net" (besides the latter still working) is the subdomain, rest of the URL remains the same and rest of the code doesn't rely on the subdomain so I'm guessing it should be straight up compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks