Skip to content

Instantly share code, notes, and snippets.

@Plazmaz
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Plazmaz/9e89bae9353d84fa5c67 to your computer and use it in GitHub Desktop.
Save Plazmaz/9e89bae9353d84fa5c67 to your computer and use it in GitHub Desktop.
Old texture invalidation and mismatching name/id implementation for Yggdrasil
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