@Override public SecurityConfig deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { SecurityConfig result = new SecurityConfig(); JsonObject jsonObject = json.getAsJsonObject(); if (jsonObject.has(SERVER_PUBLIC_CERTIFICATE)) { result.serverPublicCertificate = context.deserialize(jsonObject.getAsJsonObject(SERVER_PUBLIC_CERTIFICATE), PublicIdentityCertificate.class); } if (jsonObject.has(SERVER_PRIVATE_CERTIFICATE)) { result.serverPrivateCertificate = context.deserialize(jsonObject.getAsJsonObject(SERVER_PRIVATE_CERTIFICATE), PrivateIdentityCertificate.class); } if (jsonObject.has(CLIENT_IDENTITIES)) { JsonArray clientArray = jsonObject.getAsJsonArray(CLIENT_IDENTITIES); for (JsonElement jsonEntry : clientArray) { ClientEntry entry = context.deserialize(jsonEntry, ClientEntry.class); result.addIdentity(entry.server, new ClientIdentity(entry.clientPublic, entry.clientPrivate)); } } return result; }
public void setServerCredentials(PublicIdentityCertificate publicCert, PrivateIdentityCertificate privateCert) { checkPermission(CERTIFICATE_WRITE_PERMISSION); this.serverPublicCertificate = publicCert; this.serverPrivateCertificate = privateCert; }
private boolean validateServerIdentity() { PrivateIdentityCertificate privateCert = config.getSecurity().getServerPrivateCertificate(); PublicIdentityCertificate publicCert = config.getSecurity().getServerPublicCertificate(); if (privateCert == null || publicCert == null) { return false; } // Validate the signature if (!publicCert.verifySelfSigned()) { logger.error("Server signature is not self signed! Generating new server identity."); return false; } return true; }
private void checkServerIdentity() { if (!validateServerIdentity()) { CertificateGenerator generator = new CertificateGenerator(); CertificatePair serverIdentity = generator.generateSelfSigned(); config.getSecurity().setServerCredentials(serverIdentity.getPublicCert(), serverIdentity.getPrivateCert()); config.save(); } }
/** * @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 KEEP_LOCAL: //save for upload (remote will be overwritten) conflictSolutionsToUpload.put(server, local); break; case KEEP_REMOTE: //store the remote identity locally, overwriting the local version securityConfig.addIdentity(server, remote); break; case IGNORE: //do nothing } //if there are no more conflicts, perform the uploads and reset if (!hasConflictingIdentities()) { putIdentities(conflictSolutionsToUpload); resetConflicts(); } }
} else { try { Map<PublicIdentityCertificate, ClientIdentity> local = worker.securityConfig.getAllIdentities(); Map<PublicIdentityCertificate, ClientIdentity> remote = worker.sessionInstance.getAllIdentities(); MapDifference<PublicIdentityCertificate, ClientIdentity> diff = Maps.difference(local, remote); worker.securityConfig.addIdentity(entry.getKey(), entry.getValue());
/** * @return details about one synchronization conflict. */ public IdentityConflict getNextConflict() { IdentityBundle entry = conflictingRemoteIdentities.peekFirst(); return new IdentityConflict(entry.getServer(), securityConfig.getIdentity(entry.getServer()), entry.getClient()); }
public void exportIdentities() { FilePickerPopup filePicker = nuiManager.pushScreen(FilePickerPopup.ASSET_URI, FilePickerPopup.class); filePicker.setTitle(exportPopupTitle); filePicker.setOkHandler(path -> { Runnable action = () -> { Map<PublicIdentityCertificate, ClientIdentity> identities = securityConfig.getAllIdentities(); try (BufferedWriter writer = Files.newBufferedWriter(path, StandardOpenOption.CREATE)) { GSON.toJson(identities, MAP_TYPE, writer); nuiManager.pushScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage(exportPopupTitle, String.format(translationSystem.translate("${engine:menu#identity-export-ok}"), identities.size(), path.toString())); } catch (IOException | JsonIOException ex) { nuiManager.pushScreen(MessagePopup.ASSET_URI, MessagePopup.class) .setMessage(translationSystem.translate("${engine:menu#identity-export-fail}"), ex.toString()); } }; if (Files.exists(path)) { ConfirmPopup confirm = nuiManager.pushScreen(ConfirmPopup.ASSET_URI, ConfirmPopup.class); confirm.setMessage(exportPopupTitle, String.format(translationSystem.translate("${engine:menu#existing-file-warning}"), path.toString())); confirm.setOkHandler(action); } else { action.run(); } }); } }
@Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { logger.info("Sending Server Hello"); PublicIdentityCertificate serverPublicCert = config.getSecurity().getServerPublicCertificate(); new SecureRandom().nextBytes(serverRandom); serverHello = NetData.HandshakeHello.newBuilder() .setRandom(ByteString.copyFrom(serverRandom)) .setCertificate(NetMessageUtil.convert(serverPublicCert)) .setTimestamp(System.currentTimeMillis()) .build(); e.getChannel().write(NetData.NetMessage.newBuilder() .setHandshakeHello(serverHello) .build()); }
@Override public void perform(StorageServiceWorker worker) { try { worker.sessionInstance.logout(); worker.sessionInstance = null; worker.storageConfig.setSessionToken(null); worker.status = StorageServiceWorkerStatus.LOGGED_OUT; worker.resetConflicts(); if (deleteLocalIdentities) { worker.securityConfig.clearIdentities(); } worker.saveConfig(); worker.logMessage(false, "${engine:menu#storage-service-logout-ok}"); } catch (Exception e) { worker.status = StorageServiceWorkerStatus.LOGGED_IN; worker.logMessage(true, "${engine:menu#storage-service-logout-fail}", e.getMessage()); } } }
private void processNewIdentityRequest(NetData.NewIdentityRequest newIdentityRequest, ChannelHandlerContext ctx) { logger.info("Received new identity request"); try { byte[] preMasterSecret = config.getSecurity().getServerPrivateCertificate().decrypt(newIdentityRequest.getPreMasterSecret().toByteArray()); byte[] masterSecret = HandshakeCommon.generateMasterSecret(preMasterSecret, newIdentityRequest.getRandom().toByteArray(), serverRandom); CertificatePair clientCertificates = new CertificateGenerator().generate(config.getSecurity().getServerPrivateCertificate());
config.getSecurity().addIdentity(serverCertificate, identity); config.save();
@Before public void setup() throws Exception { super.setup(); CertificateGenerator generator = new CertificateGenerator(); CertificatePair serverIdentiy = generator.generateSelfSigned(); context.get(Config.class).getSecurity().setServerCredentials(serverIdentiy.getPublicCert(), serverIdentiy.getPrivateCert()); }
PublicIdentityCertificate server = entry.getKey(); ClientIdentity newClient = entry.getValue(); ClientIdentity oldClient = securityConfig.getIdentity(server); if (oldClient != null) { Runnable skip = () -> {
@Override public void initialise() { UIText url = find("url", UIText.class); UIText login = find("login", UIText.class); UIText password = find("password", UIText.class); find("existing-identities-warning", UILabel.class).setVisible(!config.getSecurity().getAllIdentities().isEmpty()); WidgetUtil.trySubscribe(this, "cancel", widget -> getManager().popScreen()); WidgetUtil.trySubscribe(this, "ok", widget -> { try { storageService.login(new URL(url.getText()), login.getText(), password.getText()); getManager().popScreen(); } catch (MalformedURLException e) { getManager().pushScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage( translationSystem.translate("${engine:menu#error}"), translationSystem.translate("${engine:menu#storage-service-popup-bad-url}") ); } }); } }
private void processClientHandshake(NetData.HandshakeHello clientHello, NetData.HandshakeVerification handshakeVerification, ChannelHandlerContext ctx) { logger.info("Received client certificate"); PublicIdentityCertificate clientCert = NetMessageUtil.convert(clientHello.getCertificate()); if (!clientCert.verifySignedBy(config.getSecurity().getServerPublicCertificate())) { logger.error("Received invalid client certificate, ending connection attempt"); ctx.getChannel().close(); return; } byte[] clientSignature = handshakeVerification.getSignature().toByteArray(); byte[] signatureData = HandshakeCommon.getSignatureData(serverHello, clientHello); if (!clientCert.verify(signatureData, clientSignature)) { logger.error("Received invalid verification signature, ending connection attempt"); ctx.getChannel().close(); return; } logger.info("Sending server verification"); byte[] serverSignature = config.getSecurity().getServerPrivateCertificate().sign(signatureData); ctx.getChannel().write(NetData.NetMessage.newBuilder() .setHandshakeVerification(NetData.HandshakeVerification.newBuilder() .setSignature(ByteString.copyFrom(serverSignature))).build()); // Identity has been established, inform the server handler and withdraw from the pipeline ctx.getPipeline().remove(this); serverConnectionHandler.channelAuthenticated(clientCert); }
public PrivateIdentityCertificate getServerPrivateCertificate() { checkPermission(PRIVATE_CERTIFICATE_ACCESS_PERMISSION); return serverPrivateCertificate; }
identity = config.getSecurity().getIdentity(serverCertificate); if (identity == null) { requestIdentity(ctx);
public void addIdentity(PublicIdentityCertificate serverCertificate, ClientIdentity identity) { checkPermission(CERTIFICATE_WRITE_PERMISSION); clientCertificates.put(serverCertificate, identity); }
public void clearIdentities() { checkPermission(CERTIFICATE_WRITE_PERMISSION); clientCertificates.clear(); }