Last active
August 29, 2015 14:24
-
-
Save Plazmaz/9e89bae9353d84fa5c67 to your computer and use it in GitHub Desktop.
Old texture invalidation and mismatching name/id implementation for Yggdrasil
This file contains 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
private static final long PROFILE_EXPIRATION_TIME = 300000; //5 minutes. This should be a globally scoped variable. | |
... | |
public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) { | |
Property textureProperty = (Property) Iterables.getFirst(profile.getProperties().get("textures"), null); | |
if (textureProperty == null) { | |
return new HashMap(); | |
} | |
if (requireSecure) { | |
if (!textureProperty.hasSignature()) { | |
LOGGER.error("Signature is missing from textures payload"); | |
throw new InsecureTextureException("Signature is missing from textures payload"); | |
} | |
if (!textureProperty.isSignatureValid(this.publicKey)) { | |
LOGGER.error("Textures payload has been tampered with (signature invalid)"); | |
throw new InsecureTextureException("Textures payload has been tampered with (signature invalid)"); | |
} | |
/** | |
* JSON Decoding | |
*/ | |
String textureDecodedStr; | |
try { | |
textureDecodedStr = new String(Base64.getDecoder().decode(textureProperty.getValue())); | |
} catch (IllegalArgumentException ex) { | |
LOGGER.error("Texture value is corrupted"); | |
throw new ProfileIncompleteException("Texture value is corrupted"); | |
} | |
JsonObject textureDecodedObj = (JsonObject) new JsonParser().parse(textureDecodedStr); | |
/** | |
* Handle outdated textures | |
*/ | |
long timestamp = textureDecodedObj.get("timestamp").getAsLong(); | |
Calendar expiration = Calendar.getInstance(); | |
expiration.setTime((new Date(timestamp + PROFILE_EXPIRATION_TIME))); | |
if(System.currentTimeMillis() - timestamp > PROFILE_EXPIRATION_TIME) { | |
throw new InsecureTextureException.OutdatedTextureException(new Date(timestamp), expiration); | |
} | |
/** | |
* Handle mismatching names | |
*/ | |
UUID uuid = UUIDTypeAdapter.fromString(textureDecodedObj.get("profileId").getAsString()); | |
if(!profile.getName().equals(textureDecodedObj.get("profileName").getAsString()) || | |
!profile.getId().equals(uuid)) { | |
throw new InsecureTextureException.WrongTextureOwnerException(profile, uuid, textureDecodedObj.get("profileName").getAsString()); | |
} | |
} | |
MinecraftTexturesPayload result; | |
try { | |
String json = new String(org.apache.commons.codec.binary.Base64.decodeBase64(textureProperty.getValue().getBytes()), Charsets.UTF_8); | |
result = (MinecraftTexturesPayload) this.gson.fromJson(json, MinecraftTexturesPayload.class); | |
} catch (JsonParseException e) { | |
LOGGER.error("Could not decode textures payload", e); | |
return new HashMap(); | |
} | |
if (result.getTextures() == null) { | |
return new HashMap(); | |
} | |
for (Map.Entry<MinecraftProfileTexture.Type, MinecraftProfileTexture> entry : result.getTextures().entrySet()) { | |
if (!isWhitelistedDomain(((MinecraftProfileTexture) entry.getValue()).getUrl())) { | |
LOGGER.error("Textures payload has been tampered with (non-whitelisted domain)"); | |
return new HashMap(); | |
} | |
} | |
return result.getTextures(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment