1 /*
2  * @(#) $Id: ServerCommand.java,v 1.10 2003/07/08 08:13:53 pankaj Exp $
3  *
4  * Copyright (c) 2002-03 by Pankaj Kumar (http://www.pankaj-k.net). 
5  * All rights reserved.
6  *
7  * The license governing the use of this file can be found in the 
8  * root directory of the containing software.
9  */
10package org.jstk.ssl;
11
12import java.net.*;
13import java.io.*;
14import java.util.HashMap;
15import javax.net.ServerSocketFactory;
16import javax.net.ssl.SSLServerSocketFactory;
17import javax.net.ssl.SSLServerSocket;
18import javax.net.ssl.SSLSocket;
19import javax.net.ssl.SSLSession;
20import javax.net.ssl.SSLPeerUnverifiedException;
21import java.security.cert.Certificate;
22import java.security.cert.X509Certificate;
23import org.jstk.*;
24
25public class ServerCommand extends JSTKCommandAdapter {
26
27    private static HashMap defaults = new HashMap();
28    static {
29        defaults.put("inport", "9000");
30        defaults.put("inproto", "TCP");
31        defaults.put("mode", "echo");
32        defaults.put("bufsize", "8192");
33        defaults.put("action", "read-only");
34        defaults.put("waittime", "5");
35    }
36
37    public String briefDescription(){
38        String briefDesc = "simple echo server for TCP or SSL connections";
39        return briefDesc;
40    }
41
42    public String optionsDescription(){
43        String optionsDesc =
44            "  -inport <inport>: Port No. to accept incoming connection.[" +
45            defaults.get("inport") + "]\n" +
46            "  -inproto <proto>: Incoming connection protocol (TCP|SSL|RMI|SRMI).[" +
47            defaults.get("inproto") + "]\n" +
48            "  -mode <mode>    : Receiving mode (echo|bench).[" +
49            defaults.get("mode") + "]\n" +
50            "  -action <action>: What action to take -- applicable for \"bench\" mode\n" +
51            "            (accept-wait|read-only|read-write|serve-url).[" +
52            defaults.get("action") + "]\n" +
53            "  -bufsize <bufsz>: Receiving Buffer Size (in bytes).[" +
54            defaults.get("bufsize") + "]\n" +
55            "  -needcauth      : Must authenticate client.\n" +
56            "  -wantcauth      : Negotiate to authenticate client.\n" +
57            "  -verbose        : Print a message on receiving data.\n" +
58            "  -showdata       : Show the received data on stdout.\n" +
59            "  -inetaddr <addr>: Use this IP address (useful for multi-homed hosts).\n";
60        return optionsDesc;
61    }
62    public String[] useForms(){
63        String[] useForms = {
64            "[-inport <inport>] [-ssl [-cauth]] [-inetaddr <addr>]"
65        };
66        return useForms;
67    }
68    public String[] sampleUses(){
69        String[] sampleUses = {
70            "",
71            "-inport 2950",
72            "-ssl -cauth"
73        };
74        return sampleUses;
75    }
76
77    private void ServerLoop(JSTKServerSocket jss, JSTKBuffer buf, boolean verbose,
78                        boolean bench, boolean echo, boolean invalidate){
79        int outIdx = 0;
80        while (true){
81            JSTKSocket socket = null;
82            try {
83                if (!bench || verbose)
84                    System.out.println("[" + outIdx + "]ServerLoop:: Waiting for connection ...");
85                socket = jss.accept();
86                if (!bench || verbose)
87                    System.out.println("[" + outIdx + "]ServerLoop:: ... Accepted a connection.");
88                if (!bench || verbose)
89                    JSTKSocketUtil.print(socket, " <-- ");
90            } catch (IOException ioe){
91                System.out.println("[" + outIdx + "]ServerLoop:: Exception on accept: " + ioe);
92                return;
93            }
94
95            try {
96                Thread th = new ServerThread(socket, buf, outIdx, verbose, bench, echo, invalidate);
97                th.start();
98            } catch (IOException ioe){
99                System.out.println("[" + outIdx + "]ServerLoop:: Exception starting the worker thread: " + ioe);
00                return;
01            }
02            ++outIdx;
03        }
04    }
05
06    private JSTKResult runRMIServer(JSTKArgs args, RMIServerImpl impl) throws Exception {
07        int waitTime = Integer.parseInt(args.get("waittime"));
08        int regPort = 1099;
09        try {
10            java.rmi.registry.LocateRegistry.createRegistry(regPort);
11        } catch (Exception exc){
12            return new JSTKResult(null, false, "Could not create rmiregistry in local JVM: " + exc);
13        }
14        System.out.println("RMI Registry started. Listens for requests on port: " + regPort);
15
16        String url = "//" + InetAddress.getLocalHost().getHostName()+"/RMIServer";
17        try {
18            java.rmi.Naming.rebind(url, impl);
19        } catch (Exception exc){
20            return new JSTKResult(null, false, "Could not rebind \"" + url + "\": " + exc);
21        }
22
23        System.out.println("RMIServer bound in registry. Ready to service RMI calls.");
24        System.out.println("Press Enter to exit ...");
25        System.in.read();
26        return new JSTKResult(null, true, "DONE");
27    }
28
29    private JSTKResult runRMIServer(JSTKArgs args) throws Exception {
30        int inport = Integer.parseInt(args.get("inport"));
31        RMIServerImpl impl = new RMIServerImpl(inport, new RMITCPClientSocketFactory(),
32            new RMITCPServerSocketFactory());
33        return runRMIServer(args, impl);
34    }
35
36    private JSTKResult runSRMIServer(JSTKArgs args) throws Exception {
37        int inport = Integer.parseInt(args.get("inport"));
38        RMIServerImpl impl = new RMIServerImpl(inport, new RMISSLClientSocketFactory(),
39            new RMISSLServerSocketFactory());
40        return runRMIServer(args, impl);
41    }
42
43    private JSTKResult runTCPServer(JSTKArgs args, JSTKServerSocket jss) throws Exception {
44        String mode = args.get("mode");
45        String action = args.get("action");
46        String inproto = args.get("inproto");
47        boolean verbose = Boolean.valueOf(args.get("verbose")).booleanValue();
48        boolean invalidate = Boolean.valueOf(args.get("invalidate")).booleanValue();
49        int bufsize = Integer.parseInt(args.get("bufsize"));
50
51        System.out.println("  I/O library  : " + JSTKSocketUtil.getIOLibrary(args, inproto));
52        System.out.println("  -----------------------------------");
53
54        JSTKBuffer buf = JSTKBuffer.getInstance(bufsize, args);
55        if (mode.equalsIgnoreCase("bench")){
56            if (action.equalsIgnoreCase("accept-wait")){
57                ServerLoop(jss, buf, verbose, true, false, invalidate);
58            } else if (action.equalsIgnoreCase("read-only")){
59                ServerLoop(jss, buf, verbose, true, false, invalidate);
60            } else if (action.equalsIgnoreCase("read-write")){
61                ServerLoop(jss, buf, verbose, true, true, invalidate);
62            } else {
63                return new JSTKResult(null, false, "Unknown action: " + action);
64            }
65        } else if (mode.equalsIgnoreCase("echo")){
66            ServerLoop(jss, buf, verbose, false, true, invalidate);
67        } else {
68            return new JSTKResult(null, false, "Unknown mode: " + mode);
69        }
70        return new JSTKResult(null, true, "DONE");
71    }
72
73    private JSTKResult runSSLServer(JSTKArgs args) throws Exception {
74        boolean needCAuth = Boolean.valueOf(args.get("needcauth")).booleanValue();
75        boolean wantCAuth = Boolean.valueOf(args.get("wantcauth")).booleanValue();
76        System.out.println("  Client Auth  : " +
77                    (needCAuth ? "INSIST" : (wantCAuth ? "NEGOTIATE" : "DONT ASK")));
78        String[] csarray = JSTKSocketUtil.getCSFileCipherSuites(args);
79        if (csarray != null){
80            System.out.println("  Cipher Suites to be enabled   : ");
81            for (int i = 0; i < csarray.length; i++)
82                System.out.println("         " + csarray[i]);
83        }
84
85        JSTKServerSocket jss = JSTKSocketUtil.createServerSocket(args);
86        // Preference to NeedClientAuth -- if both need and want flags are set.
87        if (needCAuth)
88            jss.setNeedClientAuth(true);
89        else if (wantCAuth)
90            jss.setWantClientAuth(true);
91        return runTCPServer(args, jss);
92    }
93
94    private JSTKResult runHTTPServer(JSTKArgs args){
95        return null;
96    }
97    private JSTKResult runHTTPSServer(JSTKArgs args){
98        return null;
99    }
00
01    public Object execute(JSTKArgs args) throws JSTKException{
02        try {
03            args.setDefaults(defaults);
04            String inport = args.get("inport");
05            String inetAddrVal = args.get("inetaddr");
06            String mode = args.get("mode");
07            String action = args.get("action");
08            String inproto = args.get("inproto");
09
10            boolean showData = Boolean.valueOf(args.get("showdata")).booleanValue();
11            boolean verbose = Boolean.valueOf(args.get("verbose")).booleanValue();
12            int bufsize = Integer.parseInt(args.get("bufsize"));
13
14            int lport = Integer.parseInt(inport);
15
16            InetAddress localHost = InetAddress.getLocalHost();
17            System.out.println("  Local Host   : " + localHost + ", Listen Port: " + lport);
18            System.out.println("  Buffer Size  : " + bufsize);
19            System.out.println("  Exec. Mode   : " + mode);
20            System.out.println("  Server Action: " + action);
21            System.out.println("  IN protocol  : " + inproto);
22
23            if (inproto.equalsIgnoreCase("RMI")){
24                return runRMIServer(args);
25            } else if (inproto.equalsIgnoreCase("SRMI")){
26                return runSRMIServer(args);
27            } else if (inproto.equalsIgnoreCase("TCP")){
28                JSTKServerSocket jss = JSTKSocketUtil.createServerSocket(args);
29                return runTCPServer(args, jss);
30            } else if (inproto.equalsIgnoreCase("SSL")){
31                return runSSLServer(args);
32            } else if (inproto.equalsIgnoreCase("HTTP")){
33                return runHTTPServer(args);
34            } else if (inproto.equalsIgnoreCase("HTTPS")){
35                return runHTTPSServer(args);
36            }
37            return new JSTKResult(null, false, "Unknown IN Protocol: " + inproto);
38        } catch (Exception exc){
39            throw new JSTKException("ServerCommand execution failed", exc);
40        }
41    }
42
43    public static void main(String[] args) throws Exception {
44        JSTKOptions opts = new JSTKOptions();
45        opts.parse(args, 0);
46        ServerCommand serverCmd = new ServerCommand();
47        JSTKResult result = (JSTKResult)serverCmd.execute(opts);
48        System.out.println(result.getText());
49        System.exit(result.isSuccess()? 0 : 1);
50    }
51}
52