Instantly share code, notes, and snippets.

Embed
What would you like to do?
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