diff --git a/src/main/java/de/sebastianvonhelmersen/Database.java b/src/main/java/de/sebastianvonhelmersen/Database.java index 0414250..33090ef 100644 --- a/src/main/java/de/sebastianvonhelmersen/Database.java +++ b/src/main/java/de/sebastianvonhelmersen/Database.java @@ -46,7 +46,7 @@ public class Database { } } - public void addPlayer(String uuid, String mcusername, LdapUser user) { + public void addPlayer(String uuid, String mcusername, user user) { String query = "insert into players values (?, ?, ?, ?, ?, ?, ?)"; try(PreparedStatement prep_query = this.statement.getConnection().prepareStatement(query)){ prep_query.setString(1, uuid); diff --git a/src/main/java/de/sebastianvonhelmersen/LdapUser.java b/src/main/java/de/sebastianvonhelmersen/User.java similarity index 73% rename from src/main/java/de/sebastianvonhelmersen/LdapUser.java rename to src/main/java/de/sebastianvonhelmersen/User.java index 034e03c..4470c0b 100644 --- a/src/main/java/de/sebastianvonhelmersen/LdapUser.java +++ b/src/main/java/de/sebastianvonhelmersen/User.java @@ -5,7 +5,7 @@ import javax.naming.directory.Attributes; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class LdapUser { +public class User { public String firstName; public String lastName; public String email; @@ -13,7 +13,16 @@ public class LdapUser { public int gid; public String ldapName; - public LdapUser(Attributes attributes) { + public User(String firstName, String lastName, String email, int uid, int gid, String ldapName) { + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.uid = uid; + this.gid = gid; + this.ldapName = ldapName; + } + + public User(Attributes attributes) { firstName = trimAttribute(attributes.get("givenname")); lastName = trimAttribute(attributes.get("sn")); email = trimAttribute(attributes.get("mail")); diff --git a/src/main/java/de/sebastianvonhelmersen/authentication/Authenticator.java b/src/main/java/de/sebastianvonhelmersen/authentication/Authenticator.java new file mode 100644 index 0000000..452413b --- /dev/null +++ b/src/main/java/de/sebastianvonhelmersen/authentication/Authenticator.java @@ -0,0 +1,8 @@ +package de.sebastianvonhelmersen.authentication; + +import de.sebastianvonhelmersen.User; + +public interface Authenticator { + public boolean authenticate(String username, String token); + public User getUser(String username); +} diff --git a/src/main/java/de/sebastianvonhelmersen/authentication/FetSite.java b/src/main/java/de/sebastianvonhelmersen/authentication/FetSite.java new file mode 100644 index 0000000..efec8b6 --- /dev/null +++ b/src/main/java/de/sebastianvonhelmersen/authentication/FetSite.java @@ -0,0 +1,55 @@ +package de.sebastianvonhelmersen.authentication; + +import de.sebastianvonhelmersen.User; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Base64; + +public class FetSite implements Authenticator { + private final byte[] masterPassword; + private final MessageDigest digest; + public FetSite(String masterPassword) { + this.masterPassword = masterPassword.getBytes(StandardCharsets.UTF_8); + + // Setup hashing Class + try { + this.digest = MessageDigest.getInstance("SHA-256"); + } + catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + /* + Token: base64(hash() XOR ) + */ + public boolean authenticate(String username, String token) { + byte[] byteToken = token.getBytes(StandardCharsets.UTF_8); + + + // Hash username to make comparison + byte[] userNameHash = digest.digest(username.getBytes(StandardCharsets.UTF_8)); + + // Decode token + // Ensure both have the same length + int length = Math.min(byteToken.length, userNameHash.length); + byte[] result = new byte[length]; + + // XOR each byte + for (int i = 0; i < length; i++) { + result[i] = (byte) (byteToken[i] ^ this.masterPassword[i]); + } + + byte[] dec_token = Base64.getDecoder().decode(result); + + // Compare hash and decoded token + return Arrays.equals(dec_token, userNameHash); + } + + public User getUser(String username) { + return new User("", "", "", 0, 0, username); + } +} diff --git a/src/main/java/de/sebastianvonhelmersen/Ldap.java b/src/main/java/de/sebastianvonhelmersen/authentication/Ldap.java similarity index 93% rename from src/main/java/de/sebastianvonhelmersen/Ldap.java rename to src/main/java/de/sebastianvonhelmersen/authentication/Ldap.java index ee15e30..8576ff0 100644 --- a/src/main/java/de/sebastianvonhelmersen/Ldap.java +++ b/src/main/java/de/sebastianvonhelmersen/authentication/Ldap.java @@ -1,4 +1,7 @@ -package de.sebastianvonhelmersen; +package de.sebastianvonhelmersen.authentication; + +import de.sebastianvonhelmersen.User; +import de.sebastianvonhelmersen.user; import javax.naming.Context; import javax.naming.NamingEnumeration; @@ -16,7 +19,7 @@ public class Ldap { private static final String LDAP_URL = "ldap://juri:389"; private static final String BASE_DN = "dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at"; private static final String ADMIN_DN = "cn=admin,dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at"; // service account - public static LdapUser authenticate(String username, String password) { + public static User authenticate(String username, String password) { try { // 1. Bind as admin/service account @@ -75,7 +78,7 @@ public class Ldap { new InitialDirContext(authEnv).close(); // bind attempt - return new LdapUser(result.getAttributes()); // success + return new user(result.getAttributes()); // success } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/de/sebastianvonhelmersen/fetmcplugin.java b/src/main/java/de/sebastianvonhelmersen/fetmcplugin.java index 28c91b1..32b1d89 100644 --- a/src/main/java/de/sebastianvonhelmersen/fetmcplugin.java +++ b/src/main/java/de/sebastianvonhelmersen/fetmcplugin.java @@ -1,5 +1,8 @@ package de.sebastianvonhelmersen; +import de.sebastianvonhelmersen.authentication.Authenticator; +import de.sebastianvonhelmersen.authentication.FetSite; +import de.sebastianvonhelmersen.authentication.Ldap; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.GameMode; @@ -23,11 +26,13 @@ import java.util.logging.Level; public class fetmcplugin extends JavaPlugin implements Listener { private Database db; private Map allInfos = HashMap.newHashMap(0); + private Authenticator authenticator; @Override public void onEnable() { // Make sure the plugin's data folder exists File dataFolder = this.getDataFolder(); + this.authenticator = new FetSite("MyokpBxpqxw9Eo8IduwH9IFSnBy4qII6"); if (!dataFolder.exists()) { dataFolder.mkdirs(); @@ -145,10 +150,10 @@ public class fetmcplugin extends JavaPlugin implements Listener { Component.text("§eBitte gib das Password deines FET Accounts ein!")); break; case AUTH_WAITING_PASSWORD: - LdapUser user = checkLdap(info.getUsername(), message.trim()); + boolean valid = validate(info.getUsername(), message.trim()); event.setCancelled(true); event.getRecipients().clear(); - if(user != null) { + if(valid) { allInfos.remove(uuid); this.db.addPlayer(uuid.toString(), event.getPlayer().getName(), user); Bukkit.getScheduler().runTask(this, () -> { @@ -177,11 +182,16 @@ public class fetmcplugin extends JavaPlugin implements Listener { return; } - - private LdapUser checkLdap(String username, String password) { + /* + * This function uses the defined Authenticator instance to authenticate the User against their + * provided username - token combination + * @param username the username used to authenticate the player with the provider + * @param token some sort of authentication methon. Can be Password, AppPassword or some other form of token the + * provider takes to authenticate the user + */ + private boolean validate(String username, String token) { getLogger().log(Level.INFO, "Checking LDAP for user " + username); - return Ldap.authenticate(username, password); - //return true; + return authenticator.authenticate(username, token); } } \ No newline at end of file