package fr.xephi.authme.datasource.mysqlextensions; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.Columns; import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.XfBCrypt; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.HooksSettings; import java.sql.Blob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.OptionalInt; /** * Extension for XFBCRYPT. */ class XfBcryptExtension extends MySqlExtension { private final String xfPrefix; private final int xfGroup; XfBcryptExtension(Settings settings, Columns col) { super(settings, col); this.xfPrefix = settings.getProperty(HooksSettings.XF_TABLE_PREFIX); this.xfGroup = settings.getProperty(HooksSettings.XF_ACTIVATED_GROUP_ID); } @Override public void saveAuth(PlayerAuth auth, Connection con) throws SQLException { OptionalInt authId = retrieveIdFromTable(auth.getNickname(), con); if (authId.isPresent()) { updateXenforoTablesOnSave(auth, authId.getAsInt(), con); } } /** * Updates the xenforo tables after a player auth has been saved. * * @param auth the player auth which was saved * @param id the account id * @param con connection to the database */ private void updateXenforoTablesOnSave(PlayerAuth auth, int id, Connection con) throws SQLException { // Insert player password, salt in xf_user_authenticate String sql = "INSERT INTO " + xfPrefix + "user_authenticate (user_id, scheme_class, data) VALUES (?,?,?)"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setInt(1, id); pst.setString(2, XfBCrypt.SCHEME_CLASS); String serializedHash = XfBCrypt.serializeHash(auth.getPassword().getHash()); byte[] bytes = serializedHash.getBytes(); Blob blob = con.createBlob(); blob.setBytes(1, bytes); pst.setBlob(3, blob); pst.executeUpdate(); } // Update player group in xf_users sql = "UPDATE " + tableName + " SET " + tableName + ".user_group_id=? WHERE " + col.NAME + "=?;"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setInt(1, xfGroup); pst.setString(2, auth.getNickname()); pst.executeUpdate(); } // Update player permission combination in xf_users sql = "UPDATE " + tableName + " SET " + tableName + ".permission_combination_id=? WHERE " + col.NAME + "=?;"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setInt(1, xfGroup); pst.setString(2, auth.getNickname()); pst.executeUpdate(); } // Insert player privacy combination in xf_user_privacy sql = "INSERT INTO " + xfPrefix + "user_privacy (user_id, allow_view_profile, allow_post_profile, " + "allow_send_personal_conversation, allow_view_identities, allow_receive_news_feed) VALUES (?,?,?,?,?,?)"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setInt(1, id); pst.setString(2, "everyone"); pst.setString(3, "members"); pst.setString(4, "members"); pst.setString(5, "everyone"); pst.setString(6, "everyone"); pst.executeUpdate(); } // Insert player group relation in xf_user_group_relation sql = "INSERT INTO " + xfPrefix + "user_group_relation (user_id, user_group_id, is_primary) VALUES (?,?,?)"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setInt(1, id); pst.setInt(2, xfGroup); pst.setString(3, "1"); pst.executeUpdate(); } } @Override public void extendAuth(PlayerAuth auth, int id, Connection con) throws SQLException { try (PreparedStatement pst = con.prepareStatement( "SELECT data FROM " + xfPrefix + "user_authenticate WHERE " + col.ID + "=?;")) { pst.setInt(1, id); try (ResultSet rs = pst.executeQuery()) { if (rs.next()) { Blob blob = rs.getBlob("data"); byte[] bytes = blob.getBytes(1, (int) blob.length()); auth.setPassword(new HashedPassword(XfBCrypt.getHashFromBlob(bytes))); } } } } @Override public void changePassword(String user, HashedPassword password, Connection con) throws SQLException { OptionalInt authId = retrieveIdFromTable(user, con); if (authId.isPresent()) { final int id = authId.getAsInt(); // Insert password in the correct table String sql = "UPDATE " + xfPrefix + "user_authenticate SET data=? WHERE " + col.ID + "=?;"; try (PreparedStatement pst = con.prepareStatement(sql)) { String serializedHash = XfBCrypt.serializeHash(password.getHash()); byte[] bytes = serializedHash.getBytes(); Blob blob = con.createBlob(); blob.setBytes(1, bytes); pst.setBlob(1, blob); pst.setInt(2, id); pst.executeUpdate(); } // ... sql = "UPDATE " + xfPrefix + "user_authenticate SET scheme_class=? WHERE " + col.ID + "=?;"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setString(1, XfBCrypt.SCHEME_CLASS); pst.setInt(2, id); pst.executeUpdate(); } } } @Override public void removeAuth(String user, Connection con) throws SQLException { OptionalInt authId = retrieveIdFromTable(user, con); if (authId.isPresent()) { String sql = "DELETE FROM " + xfPrefix + "user_authenticate WHERE " + col.ID + "=?;"; try (PreparedStatement xfDelete = con.prepareStatement(sql)) { xfDelete.setInt(1, authId.getAsInt()); xfDelete.executeUpdate(); } } } }