package org.fnppl.opensdx.file_transfer; /* * Copyright (C) 2010-2015 * fine people e.V. <opensdx@fnppl.org> * Henning Thieß <ht@fnppl.org> * * http://fnppl.org */ /* * Software license * * As far as this file or parts of this file is/are software, rather than documentation, this software-license applies / shall be applied. * * This file is part of openSDX * openSDX is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * openSDX 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 Lesser General Public License * and GNU General Public License along with openSDX. * If not, see <http://www.gnu.org/licenses/>. * */ /* * Documentation license * * As far as this file or parts of this file is/are documentation, rather than software, this documentation-license applies / shall be applied. * * This file is part of openSDX. * Permission is granted to copy, distribute and/or modify this document * under the terms of the GNU Free Documentation License, Version 1.3 * or any later version published by the Free Software Foundation; * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. * A copy of the license is included in the section entitled "GNU * Free Documentation License" resp. in the file called "FDL.txt". * */ import java.io.BufferedReader; import java.io.Console; import java.io.File; import java.io.FileReader; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Vector; import org.fnppl.opensdx.file_transfer.helper.ClientSettings; import org.fnppl.opensdx.file_transfer.helper.FileTransferLog; import org.fnppl.opensdx.file_transfer.trigger.Trigger; import org.fnppl.opensdx.file_transfer.trigger.TriggerCollection; import org.fnppl.opensdx.security.MasterKey; import org.fnppl.opensdx.security.OSDXKey; import org.fnppl.opensdx.xml.Document; import org.fnppl.opensdx.xml.Element; public class OSDXFileTransferServer { public final static String VERSION = "v.2012-07-25"; private File configFile = new File("osdxserver_config.xml"); private File alterConfigFile = new File("src/org/fnppl/opensdx/file_transfer/resources/osdxfiletransferserver_config.xml"); protected int port = 8899; protected InetAddress address = null; private int defaultMaxDirectoryDepth = -1; private TriggerCollection defaultTriggers = null; private OSDXKey mySigningKey = null; private File clients_config_file = null; private boolean backupClientsConfigOnUpdate = true; //accessable for serverthreads public FileTransferLog log = null; private int maxByteLength = 4*1024*1024; private HashMap<String, ClientSettings> clients = null; //client id := username::keyid //private HashMap<OSDXSocketServerThread, FileTransferState> states = null; public OSDXFileTransferServer(String pwS, File configFile) throws Exception { if(configFile!=null) { this.configFile = configFile; } readConfig(); if (mySigningKey!=null && !mySigningKey.isPrivateKeyUnlocked()) { mySigningKey.unlockPrivateKey(pwS); } if (mySigningKey==null || !mySigningKey.hasPrivateKey() || !mySigningKey.isPrivateKeyUnlocked()) { throw new Exception("signing key not accessable"); } } public void readConfig() { try { if (!configFile.exists()) { configFile = alterConfigFile; } if (!configFile.exists()) { System.out.println("Sorry, "+configFile.getAbsolutePath()+" not found."); System.exit(0); } Element root = Document.fromFile(configFile).getRootElement(); System.out.println("Using config-file: "+configFile.getAbsolutePath()); //uploadserver base Element ks = root.getChild("osdxfiletransferserver"); // host = ks.getChildText("host"); port = ks.getChildInt("port"); String ip4 = ks.getChildText("ipv4"); try { byte[] addr = new byte[4]; String[] sa = ip4.split("[.]"); for (int i=0;i<4;i++) { int b = Integer.parseInt(sa[i]); if (b>127) b = -256+b; addr[i] = (byte)b; } address = InetAddress.getByAddress(addr); } catch (Exception ex) { System.out.println("CAUTION: error while parsing ip adress"); ex.printStackTrace(); } defaultMaxDirectoryDepth = ks.getChildInt("max_directory_depth"); if (defaultMaxDirectoryDepth == Integer.MIN_VALUE) { defaultMaxDirectoryDepth = -1; } System.out.println("default max directory depth = "+defaultMaxDirectoryDepth); //default trigger defaultTriggers = new TriggerCollection(); Element eTriggers = ks.getChild("triggers"); if (eTriggers!=null) { Vector<Element> triggers = eTriggers.getChildren("trigger"); for (Element e : triggers) { defaultTriggers.addTrigger(Trigger.fromElement(e)); } } String logFile = ks.getChildText("logfile"); if (logFile==null) { // log = FileTransferLog.initNoLogging(); log = FileTransferLog.initTmpLog(); } else { log = FileTransferLog.initLog(new File(logFile)); } String extraClients = ks.getChildText("clients_config_file"); if (extraClients==null || extraClients.length()==0) { clients_config_file = null; } else { clients_config_file = new File(extraClients); new File(clients_config_file.getAbsolutePath()).getParentFile().mkdirs(); Element ecf = ks.getChild("clients_config_file"); String doBackup = ecf.getAttribute("backup"); if (doBackup!=null) { try { backupClientsConfigOnUpdate = Boolean.parseBoolean(doBackup); } catch (Exception ex) { backupClientsConfigOnUpdate = true; ex.printStackTrace(); } } } ///Clients clients = new HashMap<String, ClientSettings>(); //System.out.println("init clients"); Element eClients = root.getChild("clients"); Vector<Element> ecClients = eClients.getChildren("client"); for (Element e : ecClients) { try { Vector<ClientSettings> cs = ClientSettings.fromElement(e, defaultMaxDirectoryDepth, defaultTriggers); for(int i=0; i<cs.size(); i++) { ClientSettings c = cs.elementAt(i); clients.put(c.getSettingsID(), c); System.out.println("adding client: "+c.getSettingsID()+" -> "+c.getLocalRootPath().getAbsolutePath()+"\t max dir depth = "+c.getRightsAndDuties().getMaxDirectoryDepth()); if(i==0) { c.getLocalRootPath().mkdirs(); } } } catch (Exception ex) { ex.printStackTrace(); } } //clients from clients config file if (clients_config_file!=null && clients_config_file.exists()) { try { eClients = Document.fromFile(clients_config_file).getRootElement(); ecClients = eClients.getChildren("client"); for (Element e : ecClients) { try { // ClientSettings cs = ClientSettings.fromElement(e, defaultMaxDirectoryDepth); // clients.put(cs.getSettingsID(),cs); // System.out.println("adding extra client: "+cs.getSettingsID()+" -> "+cs.getLocalRootPath().getAbsolutePath()+"\t max dir depth = "+cs.getRightsAndDuties().getMaxDirectoryDepth()); // cs.getLocalRootPath().mkdirs(); Vector<ClientSettings> cs = ClientSettings.fromElement(e, defaultMaxDirectoryDepth, defaultTriggers); for(int i=0; i<cs.size(); i++) { ClientSettings c = cs.elementAt(i); clients.put(c.getSettingsID(), c); System.out.println("adding extra client: "+c.getSettingsID()+" -> "+c.getLocalRootPath().getAbsolutePath()+"\t max dir depth = "+c.getRightsAndDuties().getMaxDirectoryDepth()); if(i==0) { c.getLocalRootPath().mkdirs(); } } } catch (Exception ex) { ex.printStackTrace(); } } } catch (Exception ex2) { ex2.printStackTrace(); } } //SigningKey try { OSDXKey k = OSDXKey.fromElement(root.getChild("rootsigningkey").getChild("keypair")); if (k instanceof MasterKey) { mySigningKey = (MasterKey)k; } else { System.out.println("ERROR: no master signing key in config."); } } catch (Exception e) { System.out.println("ERROR: no master signing key in config."); } //TODO check localproofs and signatures } catch (Exception ex) { ex.printStackTrace(); } } public ClientSettings getClientSetting(String userid_keyid) { return clients.get(userid_keyid); } public void startService() throws Exception { ServerSocket so = new ServerSocket(port); if (log!=null) log.logServerStart(address.getHostAddress(), port); while (true) { try { final Socket socket = so.accept(); OSDXFileTransferServerThread t = new OSDXFileTransferServerThread(socket, mySigningKey,this); t.start(); } catch (Exception ex) { ex.printStackTrace(); Thread.sleep(250);// cooldown... } } } public static void main(String args[]) { try { if (args!=null && args.length==1 && args[0].equals("--makeconfig")) { //makeConfig(); System.out.println("makeconfig not implemented"); return; } String pwS = null; File configfile = null; if(args.length > 0 ) { configfile = new File(args[0]); if(!configfile.exists()) { pwS = args[0]; configfile = null; } } if(pwS == null) { File f = new File("osdxserver_pass.txt"); if(f.exists()) { BufferedReader bin = new BufferedReader(new FileReader(f)); String zeile = bin.readLine(); pwS = zeile.trim(); } else { Console console = System.console(); pwS = console.readLine("Please enter password for unlocking private-key: "); } } if(args.length > 1) { configfile = new File(args[1]); } OSDXFileTransferServer server = new OSDXFileTransferServer(pwS, configfile); server.startService(); } catch (Exception ex) { ex.printStackTrace(); } } }