use of org.terasology.engine.identity.ClientIdentity in project Terasology by MovingBlocks.
the class IdentityIOHelper method importIdentities.
public void importIdentities() {
FilePickerPopup filePicker = nuiManager.pushScreen(FilePickerPopup.ASSET_URI, FilePickerPopup.class);
filePicker.setTitle(importPopupTitle);
filePicker.setOkHandler(path -> {
Map<PublicIdentityCertificate, ClientIdentity> newIdentities;
try (BufferedReader reader = Files.newBufferedReader(path)) {
newIdentities = GSON.fromJson(reader, MAP_TYPE);
} catch (IOException | JsonIOException | JsonSyntaxException ex) {
nuiManager.pushScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage(translationSystem.translate("${engine:menu#identity-import-failed}"), ex.toString());
return;
}
checkNextConflict(newIdentities.entrySet().iterator(), () -> {
newIdentities.forEach(securityConfig::addIdentity);
nuiManager.pushScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage(importPopupTitle, newIdentities.isEmpty() ? translationSystem.translate("${engine:menu#identity-import-no-new}") : String.format(translationSystem.translate("${engine:menu#identity-import-ok}"), newIdentities.size()));
});
});
}
use of org.terasology.engine.identity.ClientIdentity in project Terasology by MovingBlocks.
the class IdentityIOHelper method checkNextConflict.
private void checkNextConflict(Iterator<Map.Entry<PublicIdentityCertificate, ClientIdentity>> newIdentities, Runnable onCompletion) {
Runnable next = () -> checkNextConflict(newIdentities, onCompletion);
if (newIdentities.hasNext()) {
Map.Entry<PublicIdentityCertificate, ClientIdentity> entry = newIdentities.next();
PublicIdentityCertificate server = entry.getKey();
ClientIdentity newClient = entry.getValue();
ClientIdentity oldClient = securityConfig.getIdentity(server);
if (oldClient != null) {
Runnable skip = () -> {
newIdentities.remove();
next.run();
};
if (newClient.getPlayerPublicCertificate().equals(oldClient.getPlayerPublicCertificate())) {
skip.run();
} else {
ThreeButtonPopup popup = nuiManager.pushScreen(ThreeButtonPopup.ASSET_URI, ThreeButtonPopup.class);
popup.setMessage(importPopupTitle, String.format(translationSystem.translate("${engine:menu#identity-import-conflict}"), server.getId(), oldClient.getPlayerPublicCertificate().getId(), newClient.getPlayerPublicCertificate().getId()));
popup.setLeftButton(translationSystem.translate("${engine:menu#identity-import-overwrite}"), next);
popup.setCenterButton(translationSystem.translate("${engine:menu#identity-import-skip}"), skip);
popup.setRightButton(translationSystem.translate("${engine:menu#identity-import-cancel}"), () -> nuiManager.pushScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage(importPopupTitle, translationSystem.translate("${engine:menu#identity-import-cancelled}")));
}
} else {
next.run();
}
} else {
onCompletion.run();
}
}
use of org.terasology.engine.identity.ClientIdentity in project Terasology by MovingBlocks.
the class StorageServiceWorker method solveNextConflict.
/**
* @param solution the strategy to resolve the conflict returned by the latest call to {@link
* #getNextConflict()}. If there are no more conflicts and some of the solved conflicts must keep the local
* version, the uploads are performed asynchronously.
*/
public void solveNextConflict(IdentityConflictSolution solution) {
IdentityBundle entry = conflictingRemoteIdentities.removeFirst();
PublicIdentityCertificate server = entry.getServer();
ClientIdentity remote = entry.getClient();
ClientIdentity local = securityConfig.getIdentity(server);
switch(solution) {
case // save for upload (remote will be overwritten)
KEEP_LOCAL:
conflictSolutionsToUpload.put(server, local);
break;
case // store the remote identity locally, overwriting the local version
KEEP_REMOTE:
securityConfig.addIdentity(server, remote);
break;
case IGNORE:
}
// if there are no more conflicts, perform the uploads and reset
if (!hasConflictingIdentities()) {
putIdentities(conflictSolutionsToUpload);
resetConflicts();
}
}
use of org.terasology.engine.identity.ClientIdentity in project Terasology by MovingBlocks.
the class ClientHandshakeHandler method processNewIdentity.
/**
* Generates a new secret key for a user and then decrypts the certificate into a byte array. Storing the certificate to the user ID.
* @param provisionIdentity
* @param ctx Channel Handler Context.
*/
private void processNewIdentity(NetData.ProvisionIdentity provisionIdentity, ChannelHandlerContext ctx) {
logger.info("Received identity from server");
if (!requestedCertificate) {
logger.error("Received identity without requesting it: cancelling authentication");
joinStatus.setErrorMessage(AUTHENTICATION_FAILURE);
ctx.channel().close();
return;
}
try {
byte[] decryptedCert = null;
try {
SecretKeySpec key = HandshakeCommon.generateSymmetricKey(masterSecret, clientRandom, serverRandom);
Cipher cipher = Cipher.getInstance(IdentityConstants.SYMMETRIC_ENCRYPTION_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
decryptedCert = cipher.doFinal(provisionIdentity.getEncryptedCertificates().toByteArray());
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
logger.error("Unexpected error decrypting received certificate, ending connection attempt", e);
joinStatus.setErrorMessage(AUTHENTICATION_FAILURE);
ctx.channel().close();
return;
}
NetData.CertificateSet certificateSet = NetData.CertificateSet.parseFrom(decryptedCert);
NetData.Certificate publicCertData = certificateSet.getPublicCertificate();
PublicIdentityCertificate publicCert = NetMessageUtil.convert(publicCertData);
if (!publicCert.verifySignedBy(serverCertificate)) {
logger.error("Received invalid certificate, not signed by server: cancelling authentication");
joinStatus.setErrorMessage(AUTHENTICATION_FAILURE);
ctx.channel().close();
return;
}
BigInteger exponent = new BigInteger(certificateSet.getPrivateExponent().toByteArray());
PrivateIdentityCertificate privateCert = new PrivateIdentityCertificate(publicCert.getModulus(), exponent);
// Store identity for later use
identity = new ClientIdentity(publicCert, privateCert);
config.getSecurity().addIdentity(serverCertificate, identity);
config.save();
// Try to upload the new identity to the identity storage service (if user is logged in)
StorageServiceWorker storageServiceWorker = CoreRegistry.get(StorageServiceWorker.class);
if (storageServiceWorker != null && storageServiceWorker.getStatus() == StorageServiceWorkerStatus.LOGGED_IN) {
storageServiceWorker.putIdentity(serverCertificate, identity);
}
// And we're authenticated.
ctx.pipeline().remove(this);
channelAuthenticated(ctx);
} catch (InvalidProtocolBufferException e) {
logger.error("Received invalid certificate data: cancelling authentication", e);
joinStatus.setErrorMessage(AUTHENTICATION_FAILURE);
ctx.channel().close();
}
}
Aggregations