Compare commits
3 Commits
1fc848287e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
690696b496 | ||
|
|
1115b7378f | ||
|
|
a0157292cc |
29
dec_token.py
Normal file
29
dec_token.py
Normal file
@@ -0,0 +1,29 @@
|
||||
def decode_token(username, token, masterpassword):
|
||||
|
||||
# decode the token from hex to bytes
|
||||
decoded_token = bytes.fromhex(token)
|
||||
|
||||
unsername_from_token = bytearray()
|
||||
for i in range(32):
|
||||
unsername_from_token.append(decoded_token[i] ^ ord(masterpassword[i]))
|
||||
|
||||
# remove padding
|
||||
unsername_from_token = unsername_from_token.rstrip(':'.encode())
|
||||
print("Username from token:", unsername_from_token.decode())
|
||||
|
||||
return unsername_from_token.decode() == username
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
token = input("Enter your token: ")
|
||||
username = input("Enter your username: ")
|
||||
masterpassword = input("Enter your masterpassword (32 characters): ")
|
||||
if len(masterpassword) != 32:
|
||||
print("Masterpassword must be 32 characters long")
|
||||
exit(1)
|
||||
|
||||
if decode_token(username, token, masterpassword):
|
||||
print("Token is valid")
|
||||
else:
|
||||
print("Token is invalid")
|
||||
@@ -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);
|
||||
|
||||
@@ -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"));
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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(<username>) XOR <masterpasswd>)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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<UUID, AuthInfos> 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);
|
||||
}
|
||||
|
||||
}
|
||||
26
token.py
Normal file
26
token.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Function that generates a token depending on unsername and masterpassword
|
||||
# The masterpassword must be 32 characters long!
|
||||
def create_token(username, masterpassword):
|
||||
|
||||
if len(masterpassword) != 32:
|
||||
print("Masterpassword must be 32 characters long")
|
||||
exit(1)
|
||||
|
||||
padded_username = username.ljust(32, ':')
|
||||
|
||||
token = bytearray()
|
||||
# xor connect with masterpassword to create token
|
||||
for i in range(32):
|
||||
token.append(ord(padded_username[i]) ^ ord(masterpassword[i]))
|
||||
|
||||
str_token = token.hex()
|
||||
return str_token
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# request username and masterpassword
|
||||
username = input("Enter your username: ")
|
||||
masterpassword = input("Enter your masterpassword (32 characters): ")
|
||||
|
||||
token = create_token(username, masterpassword)
|
||||
print("Your token is: " + token)
|
||||
Reference in New Issue
Block a user