[FEATURE] Support sudo

This commit is contained in:
Gravita 2024-02-07 13:47:18 +07:00
parent aa7b007616
commit 9676e55bcb
10 changed files with 113 additions and 18 deletions

View file

@ -266,7 +266,7 @@ public void invoke(String... args) throws Exception {
} }
pair.core.close(); pair.core.close();
pair.core = new RejectAuthCoreProvider(); pair.core = new RejectAuthCoreProvider();
pair.core.init(instance); pair.core.init(instance, pair);
} }
}; };
commands.put("resetauth", resetauth); commands.put("resetauth", resetauth);

View file

@ -74,7 +74,7 @@ public <T> T isSupport(Class<T> clazz) {
public void init(LaunchServer srv, String name) { public void init(LaunchServer srv, String name) {
this.name = name; this.name = name;
if (links != null) link(srv); if (links != null) link(srv);
core.init(srv); core.init(srv, this);
features = new HashSet<>(); features = new HashSet<>();
getFeatures(core.getClass(), features); getFeatures(core.getClass(), features);
if(mixes != null) { if(mixes != null) {

View file

@ -9,6 +9,7 @@
import pro.gravit.launcher.base.request.auth.password.AuthPlainPassword; import pro.gravit.launcher.base.request.auth.password.AuthPlainPassword;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthException; import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.MySQLSourceConfig; import pro.gravit.launchserver.auth.MySQLSourceConfig;
import pro.gravit.launchserver.auth.SQLSourceConfig; import pro.gravit.launchserver.auth.SQLSourceConfig;
import pro.gravit.launchserver.auth.password.PasswordVerifier; import pro.gravit.launchserver.auth.password.PasswordVerifier;
@ -66,7 +67,6 @@ public abstract class AbstractSQLCoreProvider extends AuthCoreProvider {
public transient String updateAuthSQL; public transient String updateAuthSQL;
public transient String updateServerIDSQL; public transient String updateServerIDSQL;
public transient LaunchServer server;
public abstract SQLSourceConfig getSQLConfig(); public abstract SQLSourceConfig getSQLConfig();
@ -183,8 +183,8 @@ public boolean joinServer(Client client, String username, UUID uuid, String acce
} }
@Override @Override
public void init(LaunchServer server) { public void init(LaunchServer server, AuthProviderPair pair) {
this.server = server; super.init(server, pair);
if (getSQLConfig() == null) logger.error("SQLHolder cannot be null"); if (getSQLConfig() == null) logger.error("SQLHolder cannot be null");
if (uuidColumn == null) logger.error("uuidColumn cannot be null"); if (uuidColumn == null) logger.error("uuidColumn cannot be null");
if (usernameColumn == null) logger.error("usernameColumn cannot be null"); if (usernameColumn == null) logger.error("usernameColumn cannot be null");

View file

@ -4,7 +4,10 @@
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.base.Launcher; import pro.gravit.launcher.base.Launcher;
import pro.gravit.launcher.base.events.RequestEvent;
import pro.gravit.launcher.base.events.request.AuthRequestEvent;
import pro.gravit.launcher.base.events.request.GetAvailabilityAuthRequestEvent; import pro.gravit.launcher.base.events.request.GetAvailabilityAuthRequestEvent;
import pro.gravit.launcher.base.profiles.PlayerProfile;
import pro.gravit.launcher.base.request.auth.AuthRequest; import pro.gravit.launcher.base.request.auth.AuthRequest;
import pro.gravit.launcher.base.request.auth.details.AuthPasswordDetails; import pro.gravit.launcher.base.request.auth.details.AuthPasswordDetails;
import pro.gravit.launcher.base.request.auth.password.AuthPlainPassword; import pro.gravit.launcher.base.request.auth.password.AuthPlainPassword;
@ -12,16 +15,19 @@
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.Reconfigurable; import pro.gravit.launchserver.Reconfigurable;
import pro.gravit.launchserver.auth.AuthException; import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.core.interfaces.UserHardware; import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportGetAllUsers; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportGetAllUsers;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRegistration; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRegistration;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportSudo;
import pro.gravit.launchserver.manangers.AuthManager; import pro.gravit.launchserver.manangers.AuthManager;
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.utils.ProviderMap; import pro.gravit.utils.ProviderMap;
import pro.gravit.utils.command.Command; import pro.gravit.utils.command.Command;
import pro.gravit.utils.command.SubCommand; import pro.gravit.utils.command.SubCommand;
import pro.gravit.utils.helper.VerifyHelper;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -29,6 +35,7 @@
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
/* /*
All-In-One provider All-In-One provider
@ -37,6 +44,8 @@ public abstract class AuthCoreProvider implements AutoCloseable, Reconfigurable
public static final ProviderMap<AuthCoreProvider> providers = new ProviderMap<>("AuthCoreProvider"); public static final ProviderMap<AuthCoreProvider> providers = new ProviderMap<>("AuthCoreProvider");
private static final Logger logger = LogManager.getLogger(); private static final Logger logger = LogManager.getLogger();
private static boolean registredProviders = false; private static boolean registredProviders = false;
protected transient LaunchServer server;
protected transient AuthProviderPair pair;
public static void registerProviders() { public static void registerProviders() {
if (!registredProviders) { if (!registredProviders) {
@ -71,7 +80,10 @@ public AuthManager.AuthReport authorize(User user, AuthResponse.AuthContext cont
return authorize(user.getUsername(), context, password, minecraftAccess); return authorize(user.getUsername(), context, password, minecraftAccess);
} }
public abstract void init(LaunchServer server); public void init(LaunchServer server, AuthProviderPair pair) {
this.server = server;
this.pair = pair;
}
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) { public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
return List.of(new AuthPasswordDetails()); return List.of(new AuthPasswordDetails());
@ -260,6 +272,72 @@ public void invoke(String... args) throws Exception {
}); });
} }
} }
{
var instance = isSupport(AuthSupportSudo.class);
if(instance != null) {
map.put("sudo", new SubCommand("[connectUUID] [username/uuid] [isShadow] (CLIENT/API)", "Authorize connectUUID as another user without password") {
@Override
public void invoke(String... args) throws Exception {
verifyArgs(args, 3);
UUID connectUUID = UUID.fromString(args[0]);
String login = args[1];
boolean isShadow = Boolean.parseBoolean(args[2]);
AuthResponse.ConnectTypes type;
if(args.length > 3) {
type = AuthResponse.ConnectTypes.valueOf(args[3]);
} else {
type = AuthResponse.ConnectTypes.CLIENT;
}
User user;
if(login.length() == 36) {
UUID uuid = UUID.fromString(login);
user = getUserByUUID(uuid);
} else {
user = getUserByUsername(login);
}
if(user == null) {
logger.error("User {} not found", login);
return;
}
AtomicBoolean founded = new AtomicBoolean();
server.nettyServerSocketHandler.nettyServer.service.forEachActiveChannels((ch, fh) -> {
var client = fh.getClient();
if(client == null || !connectUUID.equals(fh.getConnectUUID())) {
return;
}
logger.info("Found connectUUID {} with IP {}", fh.getConnectUUID(), fh.context == null ? "null" : fh.context.ip);
var lock = server.config.netty.performance.disableThreadSafeClientObject ? null : client.writeLock();
if(lock != null) {
lock.lock();
}
try {
var report = instance.sudo(user, isShadow);
User user1 = report.session().getUser();
server.authManager.internalAuth(client, type, pair, user1.getUsername(), user1.getUUID(), user1.getPermissions(), true);
client.sessionObject = report.session();
client.coreObject = report.session().getUser();
PlayerProfile playerProfile = server.authManager.getPlayerProfile(client);
AuthRequestEvent request = new AuthRequestEvent(user1.getPermissions(), playerProfile,
report.minecraftAccessToken(), null, null,
new AuthRequestEvent.OAuthRequestEvent(report.oauthAccessToken(), report.oauthRefreshToken(), report.oauthExpire()));
request.requestUUID = RequestEvent.eventUUID;
server.nettyServerSocketHandler.nettyServer.service.sendObject(ch, request);
} catch (Throwable e) {
logger.error("Sudo error", e);
} finally {
if(lock != null) {
lock.unlock();
}
founded.set(true);
}
});
if(!founded.get()) {
logger.error("ConnectUUID {} not found", connectUUID);
}
}
});
}
}
return map; return map;
} }

View file

@ -6,6 +6,7 @@
import pro.gravit.launcher.base.request.auth.details.AuthLoginOnlyDetails; import pro.gravit.launcher.base.request.auth.details.AuthLoginOnlyDetails;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthException; import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportSudo;
import pro.gravit.launchserver.manangers.AuthManager; import pro.gravit.launchserver.manangers.AuthManager;
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.launchserver.socket.response.auth.AuthResponse;
@ -18,7 +19,7 @@
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
public class MemoryAuthCoreProvider extends AuthCoreProvider { public class MemoryAuthCoreProvider extends AuthCoreProvider implements AuthSupportSudo {
private transient final List<MemoryUser> memory = new ArrayList<>(16); private transient final List<MemoryUser> memory = new ArrayList<>(16);
@Override @Override
@ -114,13 +115,13 @@ public boolean joinServer(Client client, String username, UUID uuid, String acce
} }
@Override @Override
public void init(LaunchServer server) { public void close() {
} }
@Override @Override
public void close() { public AuthManager.AuthReport sudo(User user, boolean shadow) throws IOException {
return authorize(user.getUsername(), null, null, true);
} }
public static class MemoryUser implements User { public static class MemoryUser implements User {

View file

@ -5,6 +5,7 @@
import pro.gravit.launcher.base.request.auth.AuthRequest; import pro.gravit.launcher.base.request.auth.AuthRequest;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthException; import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.manangers.AuthManager; import pro.gravit.launchserver.manangers.AuthManager;
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.launchserver.socket.response.auth.AuthResponse;
@ -72,7 +73,7 @@ public boolean joinServer(Client client, String username, UUID uuid, String acce
} }
@Override @Override
public void init(LaunchServer server) { public void init(LaunchServer server, AuthProviderPair pair1) {
for(var e : list) { for(var e : list) {
var pair = server.config.auth.get(e); var pair = server.config.auth.get(e);
if(pair != null) { if(pair != null) {

View file

@ -3,6 +3,7 @@
import pro.gravit.launcher.base.ClientPermissions; import pro.gravit.launcher.base.ClientPermissions;
import pro.gravit.launcher.base.request.secure.HardwareReportRequest; import pro.gravit.launcher.base.request.secure.HardwareReportRequest;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.MySQLSourceConfig; import pro.gravit.launchserver.auth.MySQLSourceConfig;
import pro.gravit.launchserver.auth.SQLSourceConfig; import pro.gravit.launchserver.auth.SQLSourceConfig;
import pro.gravit.launchserver.auth.core.interfaces.UserHardware; import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
@ -41,8 +42,8 @@ public SQLSourceConfig getSQLConfig() {
} }
@Override @Override
public void init(LaunchServer server) { public void init(LaunchServer server, AuthProviderPair pair) {
super.init(server); super.init(server, pair);
String userInfoCols = makeUserCols(); String userInfoCols = makeUserCols();
String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey"; String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey";
if (sqlFindHardwareByPublicKey == null) if (sqlFindHardwareByPublicKey == null)

View file

@ -41,11 +41,6 @@ public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext c
throw new AuthException("Please configure AuthCoreProvider"); throw new AuthException("Please configure AuthCoreProvider");
} }
@Override
public void init(LaunchServer server) {
}
@Override @Override
public User checkServer(Client client, String username, String serverID) throws IOException { public User checkServer(Client client, String username, String serverID) throws IOException {
return null; return null;

View file

@ -0,0 +1,10 @@
package pro.gravit.launchserver.auth.core.interfaces.provider;
import pro.gravit.launchserver.auth.core.User;
import pro.gravit.launchserver.manangers.AuthManager;
import java.io.IOException;
public interface AuthSupportSudo {
AuthManager.AuthReport sudo(User user, boolean shadow) throws IOException;
}

View file

@ -10,6 +10,7 @@
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -86,6 +87,14 @@ public pro.gravit.launchserver.auth.core.User getUser() {
return coreObject; return coreObject;
} }
public Lock readLock() {
return lock.readLock();
}
public Lock writeLock() {
return lock.writeLock();
}
public static class TrustLevel { public static class TrustLevel {
public byte[] verifySecureKey; public byte[] verifySecureKey;
public boolean keyChecked; public boolean keyChecked;