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);
}
}