Skip to content

Commit

Permalink
Merge pull request #159 from yushijinhun/develop
Browse files Browse the repository at this point in the history
Release v1.1.44
  • Loading branch information
yushijinhun authored May 3, 2022
2 parents 74b3e6e + dc35c04 commit ddd5081
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 102 deletions.
11 changes: 11 additions & 0 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ Configure Minecraft server with the following JVM parameter:
- Mojang namespace
- Legacy skin API polyfill
-Dauthlibinjector.httpdPort={port}
Sets the port used by the local HTTP server, defaults to 0 (randomly chosen).
-Dauthlibinjector.noShowServerName
Do not show authentication server name in Minecraft menu screen.
By default, authlib-injector alters --versionType parameter to display the authentication server name.
Expand All @@ -94,4 +97,12 @@ Configure Minecraft server with the following JVM parameter:
* Realms (allowed if the option is disabled)
* Telemetry (turned off if the option is disabled)
* Profanity filter (turned off if the option is disabled)
-Dauthlibinjector.profileKey={default|enabled|disabled}
Whether to enable the profile signing key feature. This feature is introduced in 22w17a, and is used to implement the multiplayer secure chat signing.
If this this feature is enabled, Minecraft will send a POST request to /minecraftservices/player/certificates to retrieve the key pair issued by the authentication server.
It's enabled by default if the authentication server sends feature.enable_profile_key option.
If the profile signing key isn't present, the player will be unable to join servers that enable enforce-secure-profile=true option.
And other players' Minecraft client will log a warning when receiving an unsigned chat message.
```
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ gradle
需要注意的是, authlib-injector 的日志是不会输出到 Minecraft 服务端/客户端的日志文件中的.
每次启动时日志文件都会被清空. 如果有多个进程使用同一个日志文件, 则只有最早启动的会成功打开日志文件.
每次启动时, 日志文件都会被清空. 如果有多个进程使用同一个日志文件, 则只有最早启动的会成功打开日志文件.
-Dauthlibinjector.mojangNamespace={default|enabled|disabled}
设置是否启用 Mojang 命名空间 (@mojang 后缀).
Expand Down Expand Up @@ -85,6 +85,9 @@ gradle
- Mojang 命名空间
- 旧式皮肤 API polyfill
-Dauthlibinjector.httpdPort={端口号}
设置内置 HTTP 服务器使用的端口号, 默认为 0 (随机分配).
-Dauthlibinjector.noShowServerName
不要在 Minecraft 主界面展示验证服务器名称.
默认情况下, authlib-injector 通过更改 --versionType 参数来在 Minecraft 主界面显示验证服务器名称, 使用本选项可以禁用该功能.
Expand All @@ -101,6 +104,14 @@ gradle
* 领域权限 (禁用后默认允许)
* 遥测 (禁用后默认关闭)
* 冒犯性内容过滤 (禁用后默认关闭)
-Dauthlibinjector.profileKey={default|enabled|disabled}
是否启用消息签名密钥对功能, 这一功能在 22w17a 引入, 用于多人游戏中聊天消息的数字签名.
启用此功能后, Minecraft 会向 /minecraftservices/player/certificates 发送 POST 请求, 以获取由验证服务器颁发的密钥对.
此功能需要验证服务器支持, 若验证服务器未设置 feature.enable_profile_key 选项, 则该功能默认禁用.
当缺少消息签名密钥时, 玩家将无法进入设置了 enforce-secure-profile=true 选项的服务器.
而当其他玩家的客户端在收到无有效签名的聊天消息时, 会在日志中记录警告.
```

## 捐助
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/moe/yushi/authlibinjector/AuthlibInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.util.stream.Stream;
import moe.yushi.authlibinjector.httpd.DefaultURLRedirector;
import moe.yushi.authlibinjector.httpd.LegacySkinAPIFilter;
import moe.yushi.authlibinjector.httpd.ProfileKeyFilter;
import moe.yushi.authlibinjector.httpd.AntiFeaturesFilter;
import moe.yushi.authlibinjector.httpd.QueryProfileFilter;
import moe.yushi.authlibinjector.httpd.QueryUUIDsFilter;
Expand Down Expand Up @@ -248,14 +249,19 @@ private static List<URLFilter> createFilters(APIMetadata config) {
filters.add(new AntiFeaturesFilter());
}

boolean profileKeyDefault = Boolean.TRUE.equals(config.getMeta().get("feature.enable_profile_key"));
if (!Config.profileKey.isEnabled(profileKeyDefault)) {
filters.add(new ProfileKeyFilter());
}

return filters;
}

private static ClassTransformer createTransformer(APIMetadata config) {
URLProcessor urlProcessor = new URLProcessor(createFilters(config), new DefaultURLRedirector(config));

ClassTransformer transformer = new ClassTransformer();
transformer.ignores.addAll(Config.ignoredPackages);
transformer.setIgnores(Config.ignoredPackages);

if (Config.dumpClass) {
transformer.listeners.add(new DumpClassListener(Paths.get("").toAbsolutePath()));
Expand Down
32 changes: 4 additions & 28 deletions src/main/java/moe/yushi/authlibinjector/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ public boolean isEnabled(boolean defaultValue) {
public static FeatureOption mojangNamespace;
public static FeatureOption legacySkinPolyfill;
public static FeatureOption mojangAntiFeatures;
public static FeatureOption profileKey;
public static boolean noShowServerName;
public static int httpdPort;

private static void initDebugOptions() {
String prop = System.getProperty("authlibinjector.debug");
Expand Down Expand Up @@ -105,34 +107,6 @@ private static void initDebugOptions() {
"com.sun.",
"sun.",
"net.java.",

"com.google.",
"com.ibm.",
"com.jcraft.jogg.",
"com.jcraft.jorbis.",
"com.oracle.",
"com.paulscode.",

"org.GNOME.",
"org.apache.",
"org.graalvm.",
"org.jcp.",
"org.json.",
"org.lwjgl.",
"org.objectweb.asm.",
"org.w3c.",
"org.xml.",
"org.yaml.snakeyaml.",

"gnu.trove.",
"io.netty.",
"it.unimi.dsi.fastutil.",
"javassist.",
"jline.",
"joptsimple.",
"oracle.",
"oshi.",
"paulscode.",
};

private static void initIgnoredPackages() {
Expand Down Expand Up @@ -204,7 +178,9 @@ static void init() {
mojangNamespace = parseFeatureOption("authlibinjector.mojangNamespace");
legacySkinPolyfill = parseFeatureOption("authlibinjector.legacySkinPolyfill");
mojangAntiFeatures = parseFeatureOption("authlibinjector.mojangAntiFeatures");
profileKey = parseFeatureOption("authlibinjector.profileKey");
httpdDisabled = System.getProperty("authlibinjector.disableHttpd") != null;
noShowServerName = System.getProperty("authlibinjector.noShowServerName") != null;
httpdPort = Integer.getInteger("authlibinjector.httpdPort", 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2022 Haowei Wen <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package moe.yushi.authlibinjector.httpd;

import static moe.yushi.authlibinjector.util.IOUtils.CONTENT_TYPE_JSON;
import moe.yushi.authlibinjector.AuthlibInjector;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.IHTTPSession;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.Response;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.Status;
import moe.yushi.authlibinjector.internal.org.json.simple.JSONObject;
import moe.yushi.authlibinjector.transform.PerformanceMetrics;

/**
* Authlib-injector's debug API
*/
public class DebugApiEndpoint {

public Response serve(IHTTPSession session) {
if (session.getUri().equals("/debug/metrics") && session.getMethod().equals("GET")) {
PerformanceMetrics metrics = AuthlibInjector.getClassTransformer().performanceMetrics;
JSONObject response = new JSONObject();
response.put("totalTime", metrics.getTotalTime());
response.put("matchTime", metrics.getMatchTime());
response.put("scanTime", metrics.getScanTime());
response.put("analysisTime", metrics.getAnalysisTime());
response.put("classesScanned", metrics.getClassesScanned());
response.put("classesSkipped", metrics.getClassesSkipped());
return Response.newFixedLength(Status.OK, CONTENT_TYPE_JSON, response.toJSONString());
} else {
return Response.newFixedLength(Status.NOT_FOUND, null, null);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2022 Haowei Wen <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package moe.yushi.authlibinjector.httpd;

import java.io.IOException;
import java.util.Optional;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.IHTTPSession;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.Response;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.Status;

/**
* Intercepts Minecraft's request to https://api.minecraftservices.com/player/certificates,
* and returns an empty response.
*/
public class ProfileKeyFilter implements URLFilter {

@Override
public boolean canHandle(String domain) {
return domain.equals("api.minecraftservices.com");
}

@Override
public Optional<Response> handle(String domain, String path, IHTTPSession session) throws IOException {
if (domain.equals("api.minecraftservices.com") && path.equals("/player/certificates") && session.getMethod().equals("POST")) {
return Optional.of(Response.newFixedLength(Status.NO_CONTENT, null, null));
}
return Optional.empty();
}

}
14 changes: 12 additions & 2 deletions src/main/java/moe/yushi/authlibinjector/httpd/URLProcessor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Haowei Wen <[email protected]> and contributors
* Copyright (C) 2022 Haowei Wen <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand Down Expand Up @@ -37,6 +37,7 @@
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import moe.yushi.authlibinjector.Config;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.IHTTPSession;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.IStatus;
import moe.yushi.authlibinjector.internal.fi.iki.elonen.NanoHTTPD;
Expand Down Expand Up @@ -67,6 +68,10 @@ public URLProcessor(List<URLFilter> filters, URLRedirector redirector) {
* @return the transformed URL, or empty if it doesn't need to be transformed
*/
public Optional<String> transformURL(String inputUrl) {
if (!inputUrl.startsWith("http")) {
// fast path
return Optional.empty();
}
Matcher matcher = URL_REGEX.matcher(inputUrl);
if (!matcher.find()) {
return Optional.empty();
Expand Down Expand Up @@ -98,6 +103,7 @@ private Optional<String> transform(String protocol, String domain, String path)
return redirector.redirect(domain, path);
}

private DebugApiEndpoint debugApi = new DebugApiEndpoint();
private volatile NanoHTTPD httpd;
private final Object httpdLock = new Object();

Expand All @@ -117,9 +123,13 @@ private int getLocalApiPort() {
}

private NanoHTTPD createHttpd() {
return new NanoHTTPD("127.0.0.1", 0) {
return new NanoHTTPD("127.0.0.1", Config.httpdPort) {
@Override
public Response serve(IHTTPSession session) {
if (session.getUri().startsWith("/debug/")) {
return debugApi.serve(session);
}

Matcher matcher = LOCAL_URL_REGEX.matcher(session.getUri());
if (matcher.find()) {
String protocol = matcher.group("protocol");
Expand Down
Loading

0 comments on commit ddd5081

Please sign in to comment.