View Javadoc
1   /*
2    * Copyright (c) 2005, London e-Science Centre, Imperial College London, UK
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6    *
7    * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8    * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9    * - Neither the name of the London e-Science Centre nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10   *
11   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12   */
13  package org.icenigrid.gridsam.client.cli;
14  
15  import java.io.File;
16  import java.io.FileOutputStream;
17  import java.io.IOException;
18  import java.io.OutputStream;
19  import java.io.InputStream;
20  import java.io.FileInputStream;
21  import java.net.InetAddress;
22  import java.net.UnknownHostException;
23  import java.rmi.server.UID;
24  import java.util.Properties;
25  
26  import org.apache.commons.cli.CommandLine;
27  import org.apache.commons.cli.CommandLineParser;
28  import org.apache.commons.cli.HelpFormatter;
29  import org.apache.commons.cli.OptionBuilder;
30  import org.apache.commons.cli.Options;
31  import org.apache.commons.cli.PosixParser;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  
35  import ranab.server.ftp.FtpServer;
36  
37  /**
38   * Command-line application for starting up an FTP server on the localhost for
39   * serving files
40   */
41  public class GridSAMFTPServer {
42      
43      /**
44       * logger
45       */
46      private static Log sLog = LogFactory.getLog(GridSAMFTPServer.class);
47      
48      /**
49       * CLI application main method
50       *
51       * @param pArgs
52       */
53      public static void main(String pArgs[]) {
54          HelpFormatter xFormatter = new HelpFormatter();
55          Options xOptions = new Options();
56          xOptions.addOption(OptionBuilder.withArgName("port").hasArg()
57          .isRequired().withDescription("FTP Port").create("p"));
58          xOptions.addOption(OptionBuilder.withArgName("dir").hasArg()
59          .isRequired().withDescription("Root Directory").create("d"));
60          xOptions.addOption(OptionBuilder.withArgName("localhost")
61          .withDescription("Server only available to localhost").create(
62              "l"));
63          CommandLine fCmd = null;
64          try {
65              CommandLineParser xParser = new PosixParser();
66              fCmd = xParser.parse(xOptions, pArgs);
67          } catch (Exception xEx) {
68              sLog.fatal("Invalid command-line options: " + xEx.getMessage());
69              xFormatter.printHelp(
70                  "gridsam-ftp-server: GridSAM Anonymous FTP Server", xOptions);
71              System.exit(1);
72          }
73          
74          File xRootDir = new File(fCmd.getOptionValue("d"));
75          if (!xRootDir.isDirectory()) {
76              sLog.fatal(fCmd.getOptionValue("d") + " is not a directory");
77              System.exit(2);
78          }
79          if (!xRootDir.canRead()) {
80              sLog.fatal(fCmd.getOptionValue("d") + " is not readable");
81              System.exit(3);
82          }
83          
84          // Load additional properties
85          Properties xRegistryProps = new Properties();
86          if (System.getProperty("client.configuration.properties") != null)
87          {
88              String fileName = System.getProperty("client.configuration.properties");
89              try {
90                  InputStream regPropsFile = new FileInputStream(fileName);
91                  xRegistryProps.load(regPropsFile);
92              } catch(java.io.FileNotFoundException fnfe) {
93                  System.err.println("OMII Registry properties file " + fileName + " not found. Ignoring.");
94              } catch(java.io.IOException ioe) {
95                  System.err.println("IO Exception reading OMII Registry properties file " + fileName + ". Ignoring.");
96                  System.err.println("Exception was:");
97                  ioe.printStackTrace(System.err);
98                  xRegistryProps = new Properties(); // Clear it out, just in case there was a partial read
99              }
100         }
101 
102         // change current directory to the root directory
103         // user gridsam directory
104         if (System.getProperty("user.home") == null) {
105             sLog.fatal("cannot deduce user home directory");
106             System.exit(3);
107         }
108         
109         File xHomeDir = new File(System.getProperty("user.home"), ".gridsam/");
110         if (xHomeDir.exists() && !xHomeDir.isDirectory()) {
111             sLog.fatal(xHomeDir.getAbsolutePath() + " is not a directory.");
112             System.exit(3);
113         }
114         
115         // adjust the ftp home to be the one set in the starting shell script
116         xHomeDir = new File(System.getProperty("gridsam.ftp.dir"), "ftp" + (new UID()).hashCode());
117         if (!xHomeDir.exists()) {
118             xHomeDir.mkdirs();
119         }
120 
121         File xConfigFile = null;
122         OutputStream xOS = null;
123         String xHostAddress = null;
124         try {
125             xHostAddress = System.getProperty("FtpServer.server.config.self.host");
126             if(xHostAddress == null) {
127                 xHostAddress = xRegistryProps.getProperty("default_client_ip_address");
128             }
129             xConfigFile = File.createTempFile("ftp-conf", ".properties");
130             xConfigFile.deleteOnExit();
131             Properties xProps = new Properties();
132             xProps.setProperty("FtpServer.server.config.port", fCmd
133                 .getOptionValue("p"));
134             xProps.setProperty("FtpServer.server.config.root.dir", fCmd
135                 .getOptionValue("d"));
136             if (fCmd.hasOption("l") || xHostAddress == null) {
137                 xProps.setProperty("FtpServer.server.config.self.host",
138                     "localhost");
139             } else {
140                 xProps.setProperty("FtpServer.server.config.self.host",
141                     xHostAddress);
142             }
143             xProps.setProperty("FtpServer.server.config.data", xHomeDir
144                 .getAbsolutePath());
145             xOS = new FileOutputStream(xConfigFile);
146             xProps.store(xOS, null);
147         } catch (UnknownHostException xEx) {
148             sLog.fatal("unable to determine the localhost address: "
149                 + xEx.getMessage());
150             System.exit(4);
151         } catch (IOException xEx) {
152             sLog.fatal("unable to create configuration script: "
153                 + xEx.getMessage());
154             System.exit(5);
155         } finally {
156             if (xOS != null) {
157                 try {
158                     xOS.close();
159                 } catch (Exception xEx) {
160                     // ignore
161                 }
162             }
163         }
164         
165         File xUserFile = null;
166         xOS = null;
167         try {
168             xUserFile = new File(xHomeDir, "user.properties");
169             xUserFile.createNewFile();
170             Properties xProps = new Properties();
171             xProps.setProperty("FtpServer.user.anonymous.enableflag", "true");
172             xProps.setProperty("FtpServer.user.anonymous.writepermission",
173                 "true");
174             xProps.setProperty("FtpServer.user.anonymous.userpassword", "");
175             xProps.setProperty("FtpServer.user.anonymous.homedirectory", fCmd
176                 .getOptionValue("d"));
177             xOS = new FileOutputStream(xUserFile);
178             xProps.store(xOS, null);
179         } catch (UnknownHostException xEx) {
180             sLog.fatal("unable to determine the localhost address: "
181                 + xEx.getMessage());
182             System.exit(4);
183         } catch (IOException xEx) {
184             sLog.fatal("unable to create user properties file: "
185                 + xEx.getMessage());
186             System.exit(5);
187         } finally {
188             if (xOS != null) {
189                 try {
190                     xOS.close();
191                 } catch (Exception xEx) {
192                     // ignore
193                 }
194             }
195         }
196         sLog.warn(fCmd.getOptionValue("d")
197         + " is exposed through FTP at ftp://anonymous@" + xHostAddress
198             + ":" + fCmd.getOptionValue("p") + "/");
199         sLog
200             .warn("Please make sure you understand the security implication of using anonymous FTP for file staging.");
201         // configuration file created, start ftp server
202         FtpServer.main(new String[] { xConfigFile.getAbsolutePath() });
203     }
204     
205 }