/* * * Panbox - encryption for cloud storage * Copyright (C) 2014-2015 by Fraunhofer SIT and Sirrix AG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Additonally, third party code may be provided with notices and open source * licenses from communities and third parties that govern the use of those * portions, and any licenses granted hereunder do not alter any rights and * obligations you may have under such open source licenses, however, the * disclaimer of warranty and limitation of liability provisions of the GPLv3 * will apply to all the product. * */ package org.panbox.desktop.common.gui; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import ezvcard.util.org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.panbox.Settings; import org.panbox.core.crypto.randomness.SecureRandomWrapper; import org.panbox.core.exception.RandomDataGenerationException; import org.panbox.core.pairing.PAKCorePairingHandler; import org.panbox.core.pairing.PairingInformation; import org.panbox.core.pairing.PairingNotificationReceiver; import org.panbox.core.pairing.bluetooth.BluetoothPairingInformation; import org.panbox.core.pairing.network.NetworkPairingInformation; import org.panbox.desktop.common.PanboxClient; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.image.BufferedImage; import java.net.InetAddress; import java.text.MessageFormat; import java.util.*; import java.util.Timer; public class PairNewDeviceDialog extends javax.swing.JDialog implements PairingNotificationReceiver { private static final long serialVersionUID = -6493970152852384445L; protected static final Logger logger = Logger.getLogger("org.panbox"); private static ResourceBundle bundle = ResourceBundle.getBundle( "org.panbox.desktop.common.gui.Messages", Settings.getInstance() .getLocale()); private final PanboxClient client; private final PairingInformation pInfo; private Timer timer; private TimerTask refreshTimeout; private int timeout; private String pairingPassword = null; public PairNewDeviceDialog(JFrame parent, PanboxClient client, PairingInformation pInfo) { super(parent, true); initComponents(); this.client = client; this.pInfo = pInfo; pairingModeSelectionComboBoxActionPerformed(new ActionEvent(this, 0, "init")); setVisible(true); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" // desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { pairingPanel = new javax.swing.JPanel(); pairingQrCodePanel = new javax.swing.JPanel(); pairingPasswordField = new javax.swing.JTextField(); pairingModeSelectionComboBox = new javax.swing.JComboBox<>(); cancelPairingButton = new javax.swing.JButton(); statusInfoLabel = new javax.swing.JLabel(); qrCode = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle(bundle.getString("client.deviceList.devicepairing.title")); setResizable(false); pairingPanel.setMaximumSize(new java.awt.Dimension(390, 330)); pairingPanel.setMinimumSize(new java.awt.Dimension(390, 330)); pairingQrCodePanel.setLayout(new java.awt.GridLayout(1, 1)); pairingQrCodePanel.add(qrCode); pairingPasswordField.setText(""); pairingPasswordField.setEditable(false); pairingModeSelectionComboBox .setModel(new javax.swing.DefaultComboBoxModel<>( new String[] { bundle.getString("client.deviceList.devicepairing.slave"), bundle.getString("client.deviceList.devicepairing.master") })); pairingModeSelectionComboBox .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pairingModeSelectionComboBoxActionPerformed(evt); } }); statusInfoLabel.setText(""); javax.swing.GroupLayout pairingPanelLayout = new javax.swing.GroupLayout( pairingPanel); pairingPanel.setLayout(pairingPanelLayout); pairingPanelLayout .setHorizontalGroup(pairingPanelLayout .createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addGroup( pairingPanelLayout .createSequentialGroup() .addContainerGap() .addGroup( pairingPanelLayout .createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addComponent( pairingModeSelectionComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent( pairingQrCodePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent( pairingPasswordField, javax.swing.GroupLayout.DEFAULT_SIZE, 354, Short.MAX_VALUE)) .addContainerGap())); pairingPanelLayout .setVerticalGroup(pairingPanelLayout .createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addGroup( pairingPanelLayout .createSequentialGroup() .addContainerGap() .addComponent( pairingQrCodePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( pairingPasswordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( pairingModeSelectionComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(331, Short.MAX_VALUE))); cancelPairingButton.setText(bundle.getString("client.cancel")); cancelPairingButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancelPairingButtonActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout( getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addContainerGap() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addComponent( pairingPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup( layout.createSequentialGroup() .addComponent( statusInfoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent( cancelPairingButton))) .addContainerGap())); layout.setVerticalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addContainerGap() .addComponent(pairingPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent( cancelPairingButton) .addComponent(statusInfoLabel)) .addContainerGap())); pack(); }// </editor-fold>//GEN-END:initComponents private void pairingModeSelectionComboBoxActionPerformed( java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pairingDeviceSelectionComboBoxActionPerformed stopRefreshTimer(); client.stopDevicePairing(); char[] keyPassword = null; if (evt != null && !evt.getActionCommand().equals("init") && isMasterPairing()) { keyPassword = PasswordEnterDialog .invoke(PasswordEnterDialog.PermissionType.DEVICE); if (keyPassword == null || keyPassword.length == 0) { JOptionPane.showMessageDialog(null, bundle .getString("PairNewDeviceDialog.cantPairWithEmptyPW")); } } generateNewPasswordAndUpdateDialog(); startNewRefreshTimer(); if (isMasterPairing()) { // Master will be paired! client.runMasterPairingOnPairingHandle(pInfo, pairingPassword, this, keyPassword); } else { // Slave will be paired! client.runSlavePairingOnPairingHandle(pInfo, pairingPassword, this); } if (keyPassword != null) { Arrays.fill(keyPassword, (char) 0); } }// GEN-LAST:event_pairingDeviceSelectionComboBoxActionPerformed private void cancelPairingButtonActionPerformed( java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cancelPairingButtonActionPerformed this.dispose(); }// GEN-LAST:event_cancelPairingButtonActionPerformed private void generateNewPasswordAndUpdateDialog() { try { SecureRandomWrapper secureRandom = SecureRandomWrapper .getInstance(); byte[] password = new byte[16]; secureRandom.nextBytes(password); pairingPassword = Base64.encodeBase64String(password); String addrStr = null; if (pInfo instanceof NetworkPairingInformation) { NetworkPairingInformation npi = (NetworkPairingInformation) pInfo; addrStr = ((InetAddress) npi.getPairingAddress()) .getHostAddress(); } else if (pInfo instanceof BluetoothPairingInformation) { BluetoothPairingInformation bpi = (BluetoothPairingInformation) pInfo; addrStr = bpi.getPairingAddress().toString(); // String address } pairingPasswordField.setText(addrStr + ":" + pairingPassword); BitMatrix matrix; com.google.zxing.Writer writer = new QRCodeWriter(); matrix = writer.encode(pairingPasswordField.getText(), com.google.zxing.BarcodeFormat.QR_CODE, 330, 330); BufferedImage qrCodeImage = MatrixToImageWriter .toBufferedImage(matrix); qrCode.setIcon(new ImageIcon(qrCodeImage)); } catch (WriterException e) { logger.fatal("PairNewDeviceDialog : Could not create the QR-Code from zxing library.", e); } catch (RandomDataGenerationException e) { logger.fatal("PairNewDeviceDialog : Could not obtain secure random from RNG for pairing password.", e); } } private boolean isMasterPairing() { if (pairingModeSelectionComboBox.getSelectedItem().equals( bundle.getObject("client.deviceList.devicepairing.master"))) { return true; } else { return false; } } @Override public void dispose() { super.dispose(); client.stopDevicePairing(); stopRefreshTimer(); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton cancelPairingButton; private javax.swing.JComboBox<String> pairingModeSelectionComboBox; private javax.swing.JPanel pairingPanel; private javax.swing.JTextField pairingPasswordField; private javax.swing.JPanel pairingQrCodePanel; private javax.swing.JLabel qrCode; private javax.swing.JLabel statusInfoLabel; // End of variables declaration//GEN-END:variables @Override public void inform(PairingResult result) { logger.info("PairNewDeviceDialog : Received result from pairing: " + result); this.dispose(); switch (result) { case SUCCESS: JOptionPane .showMessageDialog( null, bundle.getString("client.deviceList.devicepairing.resultmsg.success")); break; case TIMEOUT: JOptionPane .showMessageDialog( null, bundle.getString("client.deviceList.devicepairing.resultmsg.timeout")); break; case FAILED: JOptionPane .showMessageDialog( null, bundle.getString("client.deviceList.devicepairing.resultmsg.failed")); break; case QUITEFAILED: // no message since error message has been shown already. break; default: break; } } private void startNewRefreshTimer() { logger.debug("PairNewDeviceDialog : startNewRefreshTimer : Starting new refresh timeout timer."); timeout = PAKCorePairingHandler.PAIRING_TIMEOUT / 1000; refreshTimeout = new TimerTask() { @Override public void run() { logger.debug("Timeout timer started... Left: " + timeout + " seconds."); MessageFormat formatter = new MessageFormat("", Settings .getInstance().getLocale()); formatter .applyPattern(bundle .getString("client.deviceList.devicepairing.timeoutstatusbar")); statusInfoLabel.setText(formatter .format(new Object[] { timeout })); statusInfoLabel.invalidate(); timeout--; } }; timer = new Timer(); timer.schedule(refreshTimeout, new Date(), 1000); } private void stopRefreshTimer() { if (timer != null) { logger.debug("PairNewDeviceDialog : stopRefreshTimer : timer will be stopped NOW."); timer.cancel(); statusInfoLabel.setText(""); statusInfoLabel.invalidate(); } else { logger.debug("PairNewDeviceDialog : stopRefreshTimer : timer is already stopped."); } } }