package server; /** * * @author pquiring * * Created : Mar 15, 2015 */ import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javaforce.*; public class Server extends javax.swing.JFrame implements ActionListener { /** * Creates new form Server */ public Server() { initComponents(); //create tray icon to open app JFImage img = new JFImage(); img.load(getClass().getResourceAsStream("/jfrdp.png")); setIconImage(img.getImage()); img.load(getClass().getResourceAsStream("/jfrdp-tray.png")); PopupMenu popup = new PopupMenu(); show = new MenuItem("Show"); show.addActionListener(this); popup.add(show); popup.addSeparator(); exit = new MenuItem("Exit"); exit.addActionListener(this); popup.add(exit); icon = new TrayIcon(img.getImage(), "RDP", popup); icon.addActionListener(this); tray = SystemTray.getSystemTray(); try { tray.add(icon); } catch (Exception e) { JFLog.log(e); } //start service JF.initHttps(); readConfig(); JF.centerWindow(this); if (sslValid()) { service = new Service(); service.start(webPassword.getText(), rdpPassword.getText(), (Integer)maxUsers.getValue(), viewOnly.isSelected()); } } public void readConfig() { try { Properties p = new Properties(); FileInputStream fis = new FileInputStream(JF.getUserPath() + "/.jfrdp-server.cfg"); p.load(fis); fis.close(); String apass = p.getProperty("adminPassword"); if (apass == null) { apass = p.getProperty("adminEncodedPassword"); if (apass == null) { apass = ""; } else { try { apass = decodePassword(apass); } catch (Exception e) { apass = ""; } } } adminPassword.setText(apass); String wpass = p.getProperty("webPassword"); if (wpass == null) { wpass = p.getProperty("webEncodedPassword"); if (wpass == null) { wpass = ""; } else { try { wpass = decodePassword(wpass); } catch (Exception e) { wpass = ""; } } } webPassword.setText(wpass); String rpass = p.getProperty("rdpPassword"); if (rpass == null) { rpass = p.getProperty("rdpEncodedPassword"); if (rpass == null) { rpass = ""; } else { try { rpass = decodePassword(rpass); } catch (Exception e) { rpass = ""; } } } rdpPassword.setText(rpass); String users = p.getProperty("maxusers"); if (users != null) { maxUsers.setValue(JF.atoi(users)); } String view = p.getProperty("viewonly"); if (view != null && view.equals("true")) { viewOnly.setSelected(true); } } catch (Exception e) { JFLog.log(e); } } public void writeConfig() { try { Properties p = new Properties(); p.setProperty("adminEncodedPassword", encodePassword(adminPassword.getText())); p.setProperty("webEncodedPassword", encodePassword(webPassword.getText())); p.setProperty("rdpEncodedPassword", encodePassword(rdpPassword.getText())); p.setProperty("maxusers", ((Integer)maxUsers.getValue()).toString()); p.setProperty("viewonly", viewOnly.isSelected() ? "true" : "false"); FileOutputStream fos = new FileOutputStream(JF.getUserPath() + "/.jfrdp-server.cfg"); p.store(fos, "#jfRDP-server"); fos.close(); } catch (Exception e) { JFLog.log(e); } } public void restart() { if (service != null) { service.close(); service = null; JF.sleep(1000); } if (sslValid()) { service = new Service(); service.start(webPassword.getText(), rdpPassword.getText(), (Integer)maxUsers.getValue(), viewOnly.isSelected()); } } public void actionPerformed(ActionEvent e) { Object o = e.getSource(); if (o == exit) { System.exit(0); } if (o == show) { readConfig(); if (adminPassword.getText().length() > 0) { while (true) { GetPassword dialog = new GetPassword(this, true); dialog.setVisible(true); if (!dialog.accepted) { return; } if (!dialog.getPassword().equals(adminPassword.getText())) { JF.showError("Error", "Incorrect password"); continue; } else { break; } } } 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. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { save = new javax.swing.JButton(); Cancel = new javax.swing.JButton(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); webPassword = new javax.swing.JTextField(); jLabel3 = new javax.swing.JLabel(); rdpPassword = new javax.swing.JTextField(); generateSSL = new javax.swing.JButton(); status = new javax.swing.JLabel(); donate = new javax.swing.JButton(); jLabel4 = new javax.swing.JLabel(); adminPassword = new javax.swing.JTextField(); jLabel5 = new javax.swing.JLabel(); maxUsers = new javax.swing.JSpinner(); viewOnly = new javax.swing.JCheckBox(); setTitle("jfRDP Server"); save.setText("Save and Restart"); save.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveActionPerformed(evt); } }); Cancel.setText("Cancel"); Cancel.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { CancelActionPerformed(evt); } }); jLabel1.setText("RDP Configuration:"); jLabel2.setText("Web Password"); jLabel3.setText("RDP Password"); generateSSL.setText("Generate SSL Certificate"); generateSSL.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { generateSSLActionPerformed(evt); } }); status.setText("Status : ..."); donate.setText("Donate"); donate.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { donateActionPerformed(evt); } }); jLabel4.setText("Admin Password"); jLabel5.setText("Max Concurrent Users :"); maxUsers.setModel(new javax.swing.SpinnerNumberModel(1, 1, 20, 1)); viewOnly.setText("View Only"); 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) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(generateSSL) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(donate) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 37, Short.MAX_VALUE) .addComponent(Cancel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(save)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel2) .addComponent(jLabel3)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(rdpPassword) .addComponent(webPassword))) .addComponent(status, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(adminPassword)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel1) .addGroup(layout.createSequentialGroup() .addComponent(jLabel5) .addGap(18, 18, 18) .addComponent(maxUsers, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(viewOnly)) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(adminPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(webPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent(rdpPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(viewOnly) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(status) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(save) .addComponent(Cancel) .addComponent(generateSSL) .addComponent(donate))) .addGroup(layout.createSequentialGroup() .addComponent(maxUsers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void saveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveActionPerformed writeConfig(); restart(); setVisible(false); }//GEN-LAST:event_saveActionPerformed private void CancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CancelActionPerformed setVisible(false); }//GEN-LAST:event_CancelActionPerformed private void generateSSLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_generateSSLActionPerformed generateSSL(); }//GEN-LAST:event_generateSSLActionPerformed private void donateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_donateActionPerformed JF.donate(); }//GEN-LAST:event_donateActionPerformed /** * @param args the command line arguments */ public static void main(String args[]) { initSSL(); /* Create and display the form */ java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Server(); //NOTE:Do NOT make it visible (it places icon in tray) } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton Cancel; private javax.swing.JTextField adminPassword; private javax.swing.JButton donate; private javax.swing.JButton generateSSL; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JSpinner maxUsers; private javax.swing.JTextField rdpPassword; private javax.swing.JButton save; private javax.swing.JLabel status; private javax.swing.JCheckBox viewOnly; private javax.swing.JTextField webPassword; // End of variables declaration//GEN-END:variables public SystemTray tray; public TrayIcon icon; public MenuItem exit, show; public Service service; private static String getSSLfile() { return JF.getUserPath() + "/.jfrdp.key"; } private void generateSSL() { KeyMgmt.keytool(new String[] { "-genkey", "-keystore", getSSLfile(), "-keyalg", "RSA" , "-storepass", "changeme", "-keypass", "changeme" , "-dname", "CN=jfrdp.sourceforge.net,OU=jfRDP,O=jfRDP,C=CA" , "-validity", "3600" }); sslValid(); } private static void initSSL() { System.setProperty("javax.net.ssl.keyStore", getSSLfile()); System.setProperty("javax.net.ssl.keyStorePassword", "changeme"); } private boolean sslValid() { if (new File(getSSLfile()).exists()) { status.setText("Status : Ready"); return true; } status.setText("Status : SSL Certficate not found"); return false; } /** Encodes a password with some simple steps. */ public static String encodePassword(String password) { char ca[] = password.toCharArray(); int sl = ca.length; if (sl == 0) return ""; char tmp; for(int p=0;p<sl/2;p++) { tmp = ca[p]; ca[p] = ca[sl-p-1]; ca[sl-p-1] = tmp; } StringBuffer out = new StringBuffer(); for(int p=0;p<sl;p++) { ca[p] ^= 0xaa; if (ca[p] < 0x10) out.append("0"); out.append(Integer.toString(ca[p], 16)); } //System.out.println("e1=" + out.toString()); Random r = new Random(); char key = (char)(r.nextInt(0xef) + 0x10); char outkey = key; ca = out.toString().toCharArray(); sl = ca.length; for(int p=0;p<sl;p++) { ca[p] ^= key; key ^= ca[p]; } out = new StringBuffer(); for(int a=0;a<4;a++) { out.append(Integer.toString(r.nextInt(0xef) + 0x10, 16)); } out.append(Integer.toString(outkey, 16)); for(int p=0;p<sl;p++) { if (ca[p] < 0x10) out.append("0"); out.append(Integer.toString(ca[p], 16)); } for(int a=0;a<4;a++) { out.append(Integer.toString(r.nextInt(0xef) + 0x10, 16)); } return out.toString(); } /** Decodes a password. */ public static String decodePassword(String crypto) { int sl = crypto.length(); if (sl < 10) return null; char key = (char)(int)Integer.valueOf(crypto.substring(8,10), 16); char newkey; crypto = crypto.substring(10, sl - 8); int cl = (sl - 18) / 2; char ca[] = new char[cl]; for(int p=0;p<cl;p++) { ca[p] = (char)(int)Integer.valueOf(crypto.substring(p*2, p*2+2), 16); newkey = (char)(key ^ ca[p]); ca[p] ^= key; key = newkey; } crypto = new String(ca); //System.out.println("d1=" + crypto); cl = crypto.length() / 2; ca = new char[cl]; for(int p=0;p<cl;p++) { ca[p] = (char)(int)Integer.valueOf(crypto.substring(p*2, p*2+2), 16); } for(int p=0;p<cl;p++) { ca[p] ^= 0xaa; } char tmp; for(int p=0;p<cl/2;p++) { tmp = ca[p]; ca[p] = ca[cl-p-1]; ca[cl-p-1] = tmp; } return new String(ca); } }