package l2p.loginserver;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Map;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javolution.util.FastCollection.Record;
import javolution.util.FastMap;
import javolution.util.FastSet;
import l2p.Base64;
import l2p.Config;
import l2p.database.DatabaseUtils;
import l2p.database.FiltredPreparedStatement;
import l2p.database.L2DatabaseFactory;
import l2p.database.ThreadConnection;
import l2p.database.mysql;
import l2p.gameserver.templates.StatsSet;
import l2p.loginserver.crypt.Crypt;
import l2p.loginserver.crypt.ScrambledKeyPair;
import l2p.loginserver.gameservercon.AttGS;
import l2p.loginserver.gameservercon.GameServerInfo;
import l2p.loginserver.serverpackets.LoginFail.LoginFailReason;
import l2p.util.GArray;
import l2p.util.Log;
import l2p.util.NetList;
import l2p.util.Rnd;
public class LoginController
{
protected static Logger _log = Logger.getLogger(LoginController.class.getName());
private static LoginController _instance;
/**
* Time before kicking the client if he didnt logged yet
*/
private final static int LOGIN_TIMEOUT = 60 * 1000;
/**
* Clients that are on the LS but arent assocated with a account yet
*/
protected final FastSet<L2LoginClient> _clients = new FastSet<L2LoginClient>();
/**
* Authed Clients on LoginServer
*/
protected final FastMap<String, L2LoginClient> _loginServerClients = new FastMap<String, L2LoginClient>().setShared(true);
private Map<InetAddress, BanInfo> _bannedIps = new FastMap<InetAddress, BanInfo>().setShared(true);
private Map<InetAddress, FailedLoginAttempt> _hackProtection;
protected ScrambledKeyPair[] _keyPairs;
protected byte[][] _blowfishKeys;
public static Crypt DEFAULT_CRYPT;
public static Crypt[] LEGACY_CRYPT;
public static enum State
{
VALID,
WRONG,
NOT_PAID,
BANNED,
IN_USE,
IP_ACCESS_DENIED
}
public class Status
{
public float bonus = 1;
public int bonus_expire = 0;
//public boolean proxy = false;
public State state;
public void setBonus(float value)
{
bonus = value;
}
public void setBonusExpire(int value)
{
bonus_expire = value;
}
//public void setProxy(boolean value)
//{
// proxy = value;
//}
public Status setState(State value)
{
state = value;
return this;
}
}
public static void load() throws GeneralSecurityException
{
if(_instance == null)
{
_instance = new LoginController();
}
else
{
throw new IllegalStateException("LoginController can only be loaded a single time.");
}
}
public static LoginController getInstance()
{
return _instance;
}
private LoginController() throws GeneralSecurityException
{
_log.info("Loading LoginController...");
try
{
DEFAULT_CRYPT = (Crypt) Class.forName("l2p.loginserver.crypt." + Config.DEFAULT_PASSWORD_ENCODING).getMethod("getInstance", new Class[0]).invoke(null);
GArray<Crypt> legacy = new GArray<Crypt>();
for(String method : Config.LEGACY_PASSWORD_ENCODING.split(";"))
{
if(!method.equalsIgnoreCase(Config.DEFAULT_PASSWORD_ENCODING))
{
legacy.add((Crypt) Class.forName("l2p.loginserver.crypt." + method).getMethod("getInstance", new Class[0]).invoke(null));
}
}
LEGACY_CRYPT = legacy.toArray(new Crypt[legacy.size()]);
}
catch(ClassNotFoundException e)
{
_log.info("Unable to load password crypt, method not found, check config!");
e.printStackTrace();
}
catch(Exception e)
{
_log.info("Unable to load password crypt!");
e.printStackTrace();
}
_log.info("Loaded " + DEFAULT_CRYPT.getClass().getSimpleName() + " as default crypt.");
_hackProtection = new FastMap<InetAddress, FailedLoginAttempt>().setShared(true);
_keyPairs = new ScrambledKeyPair[Config.LOGIN_RSA_KEYPAIRS];
KeyPairGenerator keygen;
keygen = KeyPairGenerator.getInstance("RSA");
RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(1024, RSAKeyGenParameterSpec.F4);
keygen.initialize(spec);
//generate the initial set of keys
for(int i = 0; i < _keyPairs.length; i++)
{
_keyPairs[i] = new ScrambledKeyPair(keygen.generateKeyPair());
}
_log.info("Cached " + _keyPairs.length + " KeyPairs for RSA communication");
testCipher((RSAPrivateKey) _keyPairs[0]._pair.getPrivate());
// Store keys for blowfish communication
generateBlowFishKeys();
}
private Lock getLock(String user)
{
Lock ret = null;
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
ResultSet rset = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT `type`,`string` FROM `lock` WHERE `login` = ?");
statement.setString(1, user);
rset = statement.executeQuery();
while(rset.next())
{
if(ret == null)
{
ret = new Lock();
}
String type = rset.getString("type");
if(type.equalsIgnoreCase("IP"))
{
ret.addIP(rset.getString("string"));
}
}
}
catch(SQLException e)
{
e.printStackTrace();
}
finally
{
DatabaseUtils.closeDatabaseCSR(con, statement, rset);
}
return ret;
}
/**
* This is mostly to force the initialization of the Crypto Implementation, avoiding it being done on runtime when its first needed.<BR>
* In short it avoids the worst-case execution time on runtime by doing it on loading.
*
* @param key Any private RSA Key just for testing purposes.
* @throws GeneralSecurityException if a underlying exception was thrown by the Cipher
*/
private void testCipher(RSAPrivateKey key) throws GeneralSecurityException
{
// avoid worst-case execution, KenM
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
rsaCipher.init(Cipher.DECRYPT_MODE, key);
}
private void generateBlowFishKeys()
{
_blowfishKeys = new byte[Config.LOGIN_BLOWFISH_KEYS][16];
for(int i = 0; i < _blowfishKeys.length; i++)
{
for(int j = 0; j < _blowfishKeys[i].length; j++)
{
_blowfishKeys[i][j] = (byte) (Rnd.get(255) + 1);
}
}
_log.info("Stored " + _blowfishKeys.length + " keys for Blowfish communication");
}
/**
* @return Returns a random key
*/
public byte[] getBlowfishKey()
{
return _blowfishKeys[Rnd.get(_blowfishKeys.length)];
}
public void addLoginClient(L2LoginClient client)
{
synchronized(_clients)
{
_clients.add(client);
}
}
public void removeLoginClient(L2LoginClient client)
{
synchronized(_clients)
{
_clients.remove(client);
}
}
public SessionKey assignSessionKeyToClient()
{
SessionKey key = new SessionKey(Rnd.nextInt(), Rnd.nextInt(), Rnd.nextInt(), Rnd.nextInt());
return key;
}
public void addAuthedLoginClient(String account, L2LoginClient client)
{
synchronized(_loginServerClients)
{
_loginServerClients.put(account, client);
}
}
public L2LoginClient removeAuthedLoginClient(String account)
{
synchronized(_loginServerClients)
{
return _loginServerClients.remove(account);
}
}
public boolean isAccountInLoginServer(String account)
{
synchronized(_loginServerClients)
{
return _loginServerClients.containsKey(account);
}
}
public L2LoginClient getAuthedClient(String account)
{
synchronized(_loginServerClients)
{
return _loginServerClients.get(account);
}
}
public Status tryAuthLogin(String account, String password, L2LoginClient client)
{
Status ret;
ret = loginValid(account, password, client);
if(ret.state != State.VALID)
{
return ret;
}
if(!isAccountInLoginServer(account) && !isAccountInAnyGameServer(account))
{
// dont allow 2 simultaneous login
synchronized(_loginServerClients)
{
if(!_loginServerClients.containsKey(account))
{
addAuthedLoginClient(account, client);
}
else
{
ret.state = State.IN_USE;
}
}
// was login successful?
if(ret.state == State.VALID)
// remove him from the non-authed list
{
removeLoginClient(client);
}
}
else
{
ret.state = State.IN_USE;
}
return ret;
}
/**
* Adds the address to the ban list of the login server, with the given duration.
*
* @param address The Address to be banned.
* @param expiration Timestamp in miliseconds when this ban expires
* @throws UnknownHostException if the address is invalid.
*/
public void addBanForAddress(String address, long expiration) throws UnknownHostException
{
InetAddress netAddress = InetAddress.getByName(address);
_bannedIps.put(netAddress, new BanInfo(netAddress, expiration));
}
/**
* Adds the address to the ban list of the login server, with the given duration.
*
* @param address The Address to be banned.
* @param duration is miliseconds
*/
public void addBanForAddress(InetAddress address, long duration)
{
_bannedIps.put(address, new BanInfo(address, System.currentTimeMillis() + duration));
}
public boolean isBannedAddress(InetAddress address)
{
BanInfo bi = _bannedIps.get(address);
if(bi != null)
{
if(bi.hasExpired())
{
_bannedIps.remove(address);
return false;
}
return true;
}
return false;
}
public Map<InetAddress, BanInfo> getBannedIps()
{
return _bannedIps;
}
/**
* Remove the specified address from the ban list
*
* @param address The address to be removed from the ban list
* @return true if the ban was removed, false if there was no ban for this ip
*/
public boolean removeBanForAddress(InetAddress address)
{
return _bannedIps.remove(address) != null;
}
/**
* Remove the specified address from the ban list
*
* @param address The address to be removed from the ban list
* @return true if the ban was removed, false if there was no ban for this ip or the address was invalid.
*/
public boolean removeBanForAddress(String address)
{
try
{
return this.removeBanForAddress(InetAddress.getByName(address));
}
catch(UnknownHostException e)
{
return false;
}
}
public SessionKey getKeyForAccount(String account)
{
L2LoginClient client;
synchronized(_loginServerClients)
{
client = _loginServerClients.get(account);
}
if(client != null)
{
return client.getSessionKey();
}
return null;
}
public int getOnlinePlayerCount(int serverId)
{
GameServerInfo gsi = GameServerTable.getInstance().getRegisteredGameServerById(serverId);
if(gsi != null && gsi.isAuthed())
{
return gsi.getCurrentPlayerCount();
}
return 0;
}
public boolean isAccountInAnyGameServer(String account)
{
AttGS gst;
Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();
for(GameServerInfo gsi : serverList)
{
if((gst = gsi.getGameServer()) != null && gst.isAccountInGameServer(account))
{
return true;
}
}
return false;
}
public GameServerInfo getAccountOnGameServer(String account)
{
AttGS gst;
Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();
for(GameServerInfo gsi : serverList)
{
if((gst = gsi.getGameServer()) != null && gst.isAccountInGameServer(account))
{
return gsi;
}
}
return null;
}
public int getTotalOnlinePlayerCount()
{
int total = 0;
Collection<GameServerInfo> serverList = GameServerTable.getInstance().getRegisteredGameServers().values();
for(GameServerInfo gsi : serverList)
{
if(gsi.isAuthed())
{
total += gsi.getCurrentPlayerCount();
}
}
return total;
}
public int getMaxAllowedOnlinePlayers(int id)
{
GameServerInfo gsi = GameServerTable.getInstance().getRegisteredGameServerById(id);
if(gsi != null)
{
return gsi.getMaxPlayers();
}
return 0;
}
public boolean isLoginPossible(L2LoginClient client, int serverId)
{
GameServerInfo gsi = GameServerTable.getInstance().getRegisteredGameServerById(serverId);
int access = client.getAccessLevel();
boolean loginOk = gsi != null && gsi.isAuthed() && (gsi.getCurrentPlayerCount() < gsi.getMaxPlayers() || access >= 50);
if(loginOk && client.getLastServer() != serverId)
{
mysql.set("UPDATE accounts SET lastServer=? WHERE login=?", serverId, client.getAccount());
}
return loginOk;
}
public void setAccountAccessLevel(String user, int banLevel, String comments, int banTime)
{
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
String stmt = "UPDATE accounts SET access_level = ?, comments = ?, banExpires = ? WHERE login=?";
statement = con.prepareStatement(stmt);
statement.setInt(1, banLevel);
statement.setString(2, comments);
statement.setInt(3, banTime);
statement.setString(4, user);
statement.executeUpdate();
}
catch(Exception e)
{
_log.warning("Could not set accessLevel: " + e);
}
finally
{
DatabaseUtils.closeDatabaseCS(con, statement);
}
}
public boolean isGM(String user)
{
boolean ok = false;
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
ResultSet rset = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT access_level FROM accounts WHERE login=?");
statement.setString(1, user);
rset = statement.executeQuery();
if(rset.next())
{
int accessLevel = rset.getInt(1);
if(accessLevel >= 100)
{
ok = true;
}
}
}
catch(Exception e)
{
//_log.warning("could not check gm state:"+e);
ok = false;
}
finally
{
DatabaseUtils.closeDatabaseCSR(con, statement, rset);
}
return ok;
}
/**
* <p>This method returns one of the cached {@link ScrambledKeyPair ScrambledKeyPairs} for communication with Login Clients.</p>
*
* @return a scrambled keypair
*/
public ScrambledKeyPair getScrambledRSAKeyPair()
{
return _keyPairs[Rnd.get(_keyPairs.length)];
}
public static final String[] account_field_columns = {"pay_stat", "access_level", "bonus", "bonus_expire",
"lastServer",};
public Status loginValid(String user, String password, L2LoginClient client)// throws HackingException
{
Status ok = new Status().setState(State.WRONG);
InetAddress address = client.getConnection().getSocket().getInetAddress();
Log.add("'" + (user == null ? "null" : user) + "' " + (address == null ? "null" : address.getHostAddress()), "logins_ip");
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
ResultSet rset = null;
try
{
int lastServer = 1;
boolean paid = false;
boolean banned = false;
String phash = "";
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT password,pay_stat,access_level,bonus,bonus_expire,banExpires,lastServer,AllowIPs,lock_expire,lastactive,activated FROM accounts WHERE login=?");
statement.setString(1, user);
rset = statement.executeQuery();
if(rset.next())
{
client.account_fields = new StatsSet(rset, account_field_columns);
String allowedIps = rset.getString("AllowIPs");
int lock = rset.getInt("lock_expire");
int lastactive = rset.getInt("lastactive");
boolean expired = lock >= 0 && (lastactive + lock) * 1000L < System.currentTimeMillis();
if(!expired)
{
//TODO System.out.println("!expired");
Lock acclock = getLock(user);
if(acclock != null && !acclock.checkIP(client.getIpAddress()))
{
return new Status().setState(State.IP_ACCESS_DENIED);
}
}
else
//System.out.println("expired");
{
mysql.set("DELETE FROM `lock` WHERE login=?", user);
}
// legacy check
if(allowedIps != null && !allowedIps.isEmpty() && !allowedIps.equals("*"))
{
if(!expired)
{
NetList allowedList = new NetList();
allowedList.LoadFromString(allowedIps, ",");
if(!allowedList.isIpInNets(client.getIpAddress()))
{
return new Status().setState(State.IP_ACCESS_DENIED);
}
}
else
{
mysql.set("UPDATE `accounts` SET `AllowIPs`='*' WHERE login=?", user);
}
}
phash = rset.getString("password");
if(phash.equals(""))
{
return new Status().setState(State.WRONG);
}
paid = rset.getInt(2) == 1;
banned = rset.getInt(3) < 0;
long banTime = rset.getLong("banExpires");
if(rset.getInt("activated") == 1)
{
//TODO System.out.println("activated == 1");
int bonusTime = rset.getInt("bonus_expire");
ok.setBonus(bonusTime > System.currentTimeMillis() / 1000 || bonusTime < 0 ? rset.getFloat("bonus") : 1);
if(ok.bonus > 1)
{
ok.setBonusExpire(bonusTime);
}
}
else
{
//TODO System.out.println("activated != 1");
ok.setBonus(-1);
ok.setBonusExpire(-1);
}
//ok.setProxy(rset.getInt("proxy") == 1);
if(banTime == -1)
{
banned = true;
}
else if(banTime > 0)
{
if(banTime < System.currentTimeMillis() / 1000)
{
unBanAcc(user);
}
else
{
banned = true;
}
}
lastServer = Math.max(rset.getInt("lastServer"), 1);
if(Config.LOGIN_DEBUG)
{
_log.fine("account exists");
}
}
DatabaseUtils.closeDatabaseSR(statement, rset);
if(phash.equals(""))
{
if(Config.AUTO_CREATE_ACCOUNTS)
{
if(user != null && user.length() >= 2 && user.length() <= 14)
{
statement = con.prepareStatement("INSERT INTO accounts (login,password,lastactive,access_level,lastIP,comments) values(?,?,?,?,?,?)");
statement.setString(1, user);
statement.setString(2, DEFAULT_CRYPT.encrypt(password));
statement.setLong(3, System.currentTimeMillis() / 1000);
statement.setInt(4, 0);
statement.setString(5, address != null ? address.getHostAddress() : "");
statement.setString(6, "");
statement.execute();
DatabaseUtils.closeStatement(statement);
if(Config.LOGIN_DEBUG)
{
_log.fine("created new account for " + user);
}
return new Status().setState(State.VALID);
}
if(Config.LOGIN_DEBUG)
{
_log.fine("Invalid username creation/use attempt: " + user);
}
return new Status().setState(State.WRONG);
}
if(Config.LOGIN_DEBUG)
{
_log.fine("account missing for user " + user);
}
return new Status().setState(State.WRONG);
}
ok.setState(State.VALID);
// проверяем не зашифрован ли пароль одним из устаревших но поддерживаемых алгоритмов
boolean oldcrypt = false;
for(Crypt c : LEGACY_CRYPT)
{
if(c.compare(password, phash)) // если да то заменяем на стандартный
{
statement = con.prepareStatement("UPDATE accounts SET password=? WHERE login=?");
statement.setString(1, DEFAULT_CRYPT.encrypt(password));
statement.setString(2, user);
statement.execute();
DatabaseUtils.closeStatement(statement);
oldcrypt = true;
break;
}
}
// если старые алгоритмы не подошли проверяем стандартным
if(!oldcrypt && !DEFAULT_CRYPT.compare(password, phash))
{
return new Status().setState(State.WRONG);
}
if(!paid)
{
return new Status().setState(State.NOT_PAID);
}
if(banned)
{
return new Status().setState(State.BANNED);
}
if(ok.state == State.VALID)
{
statement = con.prepareStatement("UPDATE accounts SET lastactive=?, lastIP=? WHERE login=?");
statement.setLong(1, System.currentTimeMillis() / 1000);
statement.setString(2, address != null ? address.getHostAddress() : "");
statement.setString(3, user);
statement.execute();
client.setLastServer(lastServer);
}
}
catch(Exception e)
{
_log.warning("Could not check password:" + e);
e.printStackTrace();
ok.setState(State.WRONG);
}
finally
{
DatabaseUtils.closeDatabaseCSR(con, statement, rset);
}
if(ok.state != State.VALID)
{
Log.add("'" + user + "':'" + password + "' " + (address != null ? address.getHostAddress() : ""), "logins_ip_fails");
if(address != null)
{
FailedLoginAttempt failedAttempt = _hackProtection.get(address);
int failedCount;
if(failedAttempt == null)
{
_hackProtection.put(address, new FailedLoginAttempt(password));
failedCount = 1;
}
else
{
failedAttempt.increaseCounter(password);
failedCount = failedAttempt.getCount();
}
if(failedCount >= Config.LOGIN_TRY_BEFORE_BAN)
// TODO Configurable ban duration (10 mins for now)
{
this.addBanForAddress(address, 10 * 60 * 1000);
}
}
}
else
{
if(address != null)
{
_hackProtection.remove(address);
}
Log.add("'" + user + "' " + (address != null ? address.getHostAddress() : ""), "logins_ip");
}
return ok;
}
public void unBanAcc(String name)
{
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("UPDATE accounts SET access_level = ?, banExpires = ? WHERE login = ?");
statement.setInt(1, 0);
statement.setInt(2, 0);
statement.setString(3, name);
statement.execute();
}
catch(Exception e)
{
_log.warning("Cant unban acc " + name + ", " + e);
}
finally
{
DatabaseUtils.closeDatabaseCS(con, statement);
}
}
public boolean loginBanned(String user)
{
boolean ok = false;
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
ResultSet rset = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement("SELECT access_level FROM accounts WHERE login=?");
statement.setString(1, user);
rset = statement.executeQuery();
if(rset.next())
{
int accessLevel = rset.getInt(1);
if(accessLevel < 0)
{
ok = true;
}
}
}
catch(Exception e)
{
// digest algo not found ??
// out of bounds should not be possible
_log.warning("could not check ban state:" + e);
ok = false;
}
finally
{
DatabaseUtils.closeDatabaseCSR(con, statement, rset);
}
return ok;
}
class FailedLoginAttempt
{
//private InetAddress _ipAddress;
private int _count;
private long _lastAttempTime;
private String _lastPassword;
public FailedLoginAttempt(String lastPassword)
{
//_ipAddress = address;
_count = 1;
_lastAttempTime = System.currentTimeMillis();
_lastPassword = lastPassword;
}
public void increaseCounter(String password)
{
if(!_lastPassword.equals(password))
{
// check if theres a long time since last wrong try
if(System.currentTimeMillis() - _lastAttempTime < 5 * 60 * 1000)
{
_count++;
}
else
// restart the status
{
_count = 1;
}
_lastPassword = password;
_lastAttempTime = System.currentTimeMillis();
}
else
{
_lastAttempTime = System.currentTimeMillis();
}
}
public int getCount()
{
return _count;
}
}
public class BanInfo
{
private InetAddress _ipAddress;
// Expiration
private long _expiration;
public BanInfo(InetAddress ipAddress, long expiration)
{
_ipAddress = ipAddress;
_expiration = expiration;
}
public InetAddress getAddress()
{
return _ipAddress;
}
public boolean hasExpired()
{
return System.currentTimeMillis() > _expiration;
}
}
class PurgeThread extends Thread
{
@Override
public void run()
{
while(true)
{
synchronized(_clients)
{
for(Record e = _clients.head(), end = _clients.tail(); (e = e.getNext()) != end;)
{
L2LoginClient client = _clients.valueOf(e);
if(client.getConnectionStartTime() + LOGIN_TIMEOUT >= System.currentTimeMillis())
{
client.close(LoginFailReason.REASON_ACCESS_FAILED);
}
}
}
synchronized(_loginServerClients)
{
for(FastMap.Entry<String, L2LoginClient> e = _loginServerClients.head(), end = _loginServerClients.tail(); (e = e.getNext()) != end;)
{
L2LoginClient client = e.getValue();
if(client.getConnectionStartTime() + LOGIN_TIMEOUT >= System.currentTimeMillis())
{
client.close(LoginFailReason.REASON_ACCESS_FAILED);
}
}
}
try
{
Thread.sleep(2 * LOGIN_TIMEOUT);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public boolean ipBlocked(String ipAddress)
{
int tries = 0;
InetAddress ia;
try
{
ia = InetAddress.getByName(ipAddress);
}
catch(UnknownHostException e)
{
return false;
}
if(_hackProtection.containsKey(ia))
{
tries = _hackProtection.get(ia).getCount();
}
if(tries > Config.LOGIN_TRY_BEFORE_BAN)
{
_hackProtection.remove(ia);
_log.warning("Removed host from hacklist! IP number: " + ipAddress);
return true;
}
return false;
}
public boolean setPassword(String account, String password)
{
boolean updated = true;
ThreadConnection con = null;
FiltredPreparedStatement statement = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
MessageDigest md = MessageDigest.getInstance("SHA");
byte[] raw = password.getBytes("UTF-8");
byte[] hash = md.digest(raw);
statement = con.prepareStatement("UPDATE accounts SET password=? WHERE login=?");
statement.setString(1, Base64.encodeBytes(hash));
statement.setString(2, account);
statement.execute();
}
catch(Exception e)
{
e.printStackTrace();
updated = false;
}
finally
{
DatabaseUtils.closeDatabaseCS(con, statement);
}
return updated;
}
}