* ===========================================================================

 * Licensed Materials - Property of IBM

 * IBM Security Software Development Kit, Java (tm) Technology Edition

 *

 * (C) Copyright IBM Corp. 2002, 2005 All Rights Reserved.

 *

 *  US Government Users Restricted Rights - Use, duplication or

 *  disclosure restricted by GSA ADP Schedule Contract with IBM Corp.

 * ===========================================================================

 

package com.ibm.security.jgss.test;

 

import org.ietf.jgss.*;

import com.ibm.security.jgss.Debug;

import java.io.*;

import java.net.*;

import java.util.*;

 

/**

 * A JGSS sample server; to be used in conjunction with a JGSS sample client.

 * <p>

 * It continuously listens for client connections,

 * spawning a thread to service an incoming connection.

 * It is capable of running multiple threads concurrently.

 * In other words, it can service multiple clients concurrently.

 * <p>

 * Each thread first establishes a context with the client

 * and then waits for a wrapped message followed by a MIC.

 * It assumes that the client calculated the MIC over the plain

 * text wrapped by the client.

 * <p>

 * If the client delegates its credential to the server, the delegated

 * credential is used to communicate with a secondary server.

 * <p>

 * Also, the server can be started to act as a client as well as

 * a server (using the <code>-b</code> option). In this case, the first

 * thread spawned by the server uses the server principal's own credential

 * to communicate with the secondary server.

 * <p>

 * The secondary server must have been started prior to the (primary) server

 * initiating contact with it (the scondary server).

 * In communicating with the secondary server, the primary server acts as

 * a JGSS initiator (i.e., client), establishing a context and engaging in

 * wrap and MIC per-message exchanges with the secondary server.

 * <p>

 * The server takes input parameters, and complements it

 * with information from the jgss.ini file; any required input not

 * supplied on the command line is taking from the jgss.ini file.

 * Built-in defaults are used if there is no jgss.ini file or if a particular

 * variable is not specified in the ini file.

 * <p>

 * Usage: Server [options]

 * <p>

 * The -? option produces a help message including supported options.

 * <p>

 * This sample server does not use JAAS.

 * It sets the JAVA variable

 * <code>javax.security.auth.useSubjectCredsOnly</code> to <code>false</code>

 * so that JGSS will not acquire credentials through JAAS.

 * The server can be run against the JAAS sample clients and servers.

 * See {@link JAASServer JAASServer} for a sample server that uses JAAS.

 *

 * @author Thomas Owusu

 */

 

// Secondary server uses ByteArray streams.

 

class Server implements Runnable

{

    /*

     * NOTES:

     * This class, Server, is expected to be run in concurrent

     * multiple threads. The static variables consist of variables

     * set from command-line arguments and variables (such as

     * the server's own credentials, gssCred) that are set once during

     * during initialization. These variables do not change

     * once set and are shared between all running threads.

     *

     * The only static variable that is changed after being set initially

     * is the variable 'beenInitiator' which is set 'true'

     * by the first thread to run the server as initiator using

     * the server's own creds. This ensures the server is run as an initiator

     * once only. Querying and modifying 'beenInitiator' is synchronized

     * between the threads.

     *

     * The variable 'tcp' is non-static and is set per thread

     * to represent the socket on which the client being serviced

     * by the thread connected.

     */

 

    private static Util testUtil    = null;

    private static int myPort       = 0;

    private static Debug debug            = new Debug();

    private static String myName    = null;

    private static GSSCredential gssCred= null;

    private static String serviceNameNoRealm= null;

    private static String serviceHost     = null;

    private static int    servicePort     = 0;

    private static String serviceMsg      = null;

    private static GSSManager mgr   = null;

    private static GSSName gssName  = null;

    private static String program   = "Server";

    private static boolean clientServer   = false;

    private static boolean primaryServer= true;

    private static boolean beenInitiator= false;

    private static boolean useStreams= false;

 

    private static final String usageString =

         "\t[-?] [-# number] [-n name] [-p port]"

       + "\n\t[-s serverName] [-h serverHost [:port]] [-P serverPort] [-m msg]"

       + "\n"

       + "\n  -?\t\t\thelp; produces this message"

       + "\n  -# number\t\tWhether primary or secondary server"

       +         " \n\t\t\t(1 = primary, 2 = secondary; default = first)"

       + "\n  -n name\t\tthe server's principal name (without realm)"

       + "\n  -p port\t\tthe port on which the server will be listening"

       + "\n  -s serverName\t\tsecondary server's principal name"

       +         " (without realm)"

       + "\n  -h serverHost[:port]\tsecondary server's hostname"

       +         " (and optional port number)"

       + "\n  -P port\t\tsecondary server's port number"

       + "\n  -m msg\t\tmessage to send to secondary server"

       + "\n  -b \t\trun as both client and server"

       +         " using the server's owns credentials";

 

    // Non-static variables are thread-specific

    // since each thread runs a separate instance of this class.

 

    private String debugPrefix      = null;

    private TCPComms tcp      = null;

 

    static {

        try {

            testUtil = new Util();

        } catch (Exception exc) {

            exc.printStackTrace();

            System.exit(1);

        }

    }

 

    Server (Socket socket) throws Exception

    {

        debugPrefix = program + ": ";

        tcp = new TCPComms(socket);

    }

 

    Server (String program) throws Exception

    {

        debugPrefix = program + ": ";

        this.program = program;

    }

 

    Server (String program, boolean useSubjectCredsOnly) throws Exception

    {

        this(program);

        setUseSubjectCredsOnly(useSubjectCredsOnly);

    }

 

    void setUseSubjectCredsOnly(boolean useSubjectCredsOnly)

    {

        final String subjectOnly = useSubjectCredsOnly ? "true" : "false";

        final String property = "javax.security.auth.useSubjectCredsOnly";

 

        String temp = (String)java.security.AccessController.doPrivileged(

                        new sun.security.action.GetPropertyAction(property));

 

        if (temp == null)

        {

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

              + "setting useSubjectCredsOnly property to "

              + (useSubjectCredsOnly ? "true" : "false"));

 

            // Property not set. Set it to the specified value.

 

            java.security.AccessController.doPrivileged(

                 new java.security.PrivilegedAction() {

                   public Object run() {

                      System.setProperty(property, subjectOnly);

                      return null;

                   }

                 });

        }

        else

        {

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

              + "useSubjectCredsOnly property already set "

              + "in JVM  to " + temp);

        }

    }

 

    private void init(boolean primary,

              String    myNameWithoutRealm,

              int       port,

              String    serverNameWithoutRealm,

              String    serverHostname,

              int       serverPort,

              String    message,

              boolean   clientServer)

        throws Exception

    {

        primaryServer = primary;

        if (!primaryServer) {

            useStreams = true;

            debug.out(Debug.OPTS_CAT_APPLICATION,

                             debugPrefix + "Using streams");

        }

        this.clientServer = clientServer;

 

        myName = myNameWithoutRealm;

 

        // my port

        if (port > 0)

        {

            myPort = port;

        }

        else if (primary)

        {

            myPort = testUtil.getDefaultServicePort();

        }

        else

        {

            myPort = testUtil.getDefaultService2Port();

        }

 

        if (primary)

        {

            ///// peer's name

            if (serverNameWithoutRealm != null)

            {

                serviceNameNoRealm = serverNameWithoutRealm;

            }

            else

            {

                serviceNameNoRealm =

                      testUtil.getDefaultService2PrincipalWithoutRealm();

            }

   

            // peer's host

            if (serverHostname != null)

            {

                if (serverHostname.equalsIgnoreCase("localHost"))

                {

                    serverHostname = InetAddress.getLocalHost().getHostName();

                }

   

                serviceHost = serverHostname;

            }

            else

            {

                serviceHost = testUtil.getDefaultService2Hostname();

            }

   

            // peer's port

            if (serverPort > 0)

            {

                servicePort = serverPort;

            }

            else

            {

                servicePort = testUtil.getDefaultService2Port();

            }

   

            // message for peer

            if (message != null)

            {

                serviceMsg = message;

            }

            else

            {

                serviceMsg = "Hi there! I am an acceptor."

                              + " But I can be an initiator, too";

            }

        }

 

        String temp = debugPrefix + "details"

                      + "\n\tPrimary:\t" + primary

                      + "\n\tName:\t\t" + myName

                      + "\n\tPort:\t\t" + myPort

                      + "\n\tClient+server:\t" + clientServer;

        if (primary)

        {

            temp += "\n\tOther Server:"

                      + "\n\t\tName:\t" + serviceNameNoRealm

                      + "\n\t\tHost:\t" + serviceHost

                      + "\n\t\tPort:\t" + servicePort

                      + "\n\t\tMsg:\t" + serviceMsg;

        }

 

        debug.out(Debug.OPTS_CAT_APPLICATION, temp);

    }

 

 

    void initialize() throws GSSException

    {

            debug.out(Debug.OPTS_CAT_APPLICATION,

                         debugPrefix + "creating GSSManager");

 

        mgr = GSSManager.getInstance();

 

        int usage = clientServer ? GSSCredential.INITIATE_AND_ACCEPT

                                 : GSSCredential.ACCEPT_ONLY;

      

        if (myName != null)

        {

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                               + "creating GSSName for " + myName);

   

            gssName = mgr.createName(myName,

                                     GSSName.NT_HOSTBASED_SERVICE);

 

            Oid krb5MechanismOid = new Oid("1.2.840.113554.1.2.2");

            gssName.canonicalize(krb5MechanismOid);

            //gssName.canonicalize(GSSManagerImpl.MECH_TYPE_KRB5);

   

            myName = gssName.toString();

 

            debug.out(Debug.OPTS_CAT_APPLICATION,

                  debugPrefix + "Canonicalized GSSName=" + gssName);

        }

        else

            gssName = null;

   

        debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "creating"

               + ((gssName == null)? " default " : " ")

               + "credential");

 

        gssCred = mgr.createCredential(

                               gssName, GSSCredential.DEFAULT_LIFETIME,

                               (Oid)null, usage);

        if (gssName == null)

        {

            gssName = gssCred.getName();

            myName = gssName.toString();

 

            debug.out(Debug.OPTS_CAT_APPLICATION,

               debugPrefix + "default credential principal=" + myName);

        }

 

        int lifetime = gssCred.getRemainingLifetime();

        debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                   + "lifetime remaining on cred: " + lifetime + " secs");

 

        Oid[] mechs = gssCred.getMechs();

 

        if (usage == GSSCredential.INITIATE_AND_ACCEPT) {

            lifetime = gssCred.getRemainingInitLifetime(mechs[0]);

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                 + "Init lifetime remaining on cred for mech " + mechs[0]

                      + ": " + lifetime + " secs");

        }

 

        lifetime = gssCred.getRemainingAcceptLifetime(mechs[0]);

        debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

              + "Accept lifetime remaining on cred for mech " + mechs[0]

                 + ": " + lifetime + " secs");

 

        debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + gssCred);

    }

 

 

 

    void processArgs(String[] args) throws Exception {

        String port     = null;

        String name     = null;

        int iport = 0;

 

        String sport    = null;

        int isport      = 0;

        String sname    = null;

        String shost    = null;

        String smessage = null;

 

        boolean primary = true;

        String status   = null;

 

        boolean clientServer = false;

 

        if (args != null && args.length > 0) {

            for (int i=0; i<args.length; i++) {

                if ("-?".equals(args[i])) {

                    printUsage();

                    System.exit(1);

                } else if ("-#".equals(args[i])) {

                    if (status == null) {

                        if (i+1 >= args.length) {

                            noArgForOptionError("-#");

                        }

                        status = args[++i];

                        continue;

                    } else {

                        duplicateOptionError("-#");

                    }

                } else if ("-p".equals(args[i])) {

                    if (port == null) {

                        if (i+1 >= args.length) {

                            noArgForOptionError("-p");

                        }

                        port = args[++i];

                        continue;

                    } else {

                        duplicateOptionError("-p");

                    }

                } else if ("-n".equals(args[i])) {

                    if (name == null) {

                        if (i+1 >= args.length) {

                            noArgForOptionError("-n");

                        }

                        name = args[++i];

                        continue;

                    } else {

                        duplicateOptionError("-n");

                    }

                } else if ("-b".equals(args[i])) {

                    if (!clientServer) {

                        clientServer = true;

                        continue;

                    } else {

                        duplicateOptionError("-b");

                    }

                } else if ("-P".equals(args[i])) { ////// The other server

                    if (sport == null) {

                        if (i+1 >= args.length) {

                            noArgForOptionError("-P");

                        }

                        sport = args[++i];

                        continue;

                    } else {

                        duplicateOptionError("-P");

                    }

                } else if ("-m".equals(args[i])) {

                    if (smessage == null) {

                        if (i+1 >= args.length) {

                            noArgForOptionError("-m");

                        }

                        smessage = args[++i];

                        continue;

                    } else {

                        duplicateOptionError("-m");

                    }

                } else if ("-s".equals(args[i])) {

                    if (sname == null) {

                        if (i+1 >= args.length) {

                            noArgForOptionError("-s");

                        }

                        sname = args[++i];

                        continue;

                    } else {

                        duplicateOptionError("-s");

                    }

                } else if ("-h".equals(args[i])) {

                    if (shost == null) {

                        if (i+1 >= args.length) {

                            noArgForOptionError("-h");

                        }

                        shost = args[++i];

                        int p = shost.indexOf(':');

                        if (p != -1) {

                            String temp1 = shost.substring(0, p);

                            if (sport == null)

                                sport = shost.substring

                                               (p+1, shost.length()).trim();

                            shost = temp1;

                        }

                        continue;

                    } else {

                        duplicateOptionError("-h");

                    }

                }

            }

        }

 

        if (status != null)

        {

            int p = -1;

            try {

                p = Integer.parseInt(status);

            } catch (Exception exc) {

                System.out.println( "Bad status input: "+status);

            }

 

            if (p != -1)

            {

                primary = (p == 1);

            }

        }

 

        if (port != null)

        {

            int p = -1;

            try {

                p = Integer.parseInt(port);

            } catch (Exception exc) {

                System.out.println( "Bad port input: "+port);

            }

            if (p != -1)

                iport = p;

        }

 

        if (sport != null)

        {

            int p = -1;

            try {

                p = Integer.parseInt(sport);

            } catch (Exception exc) {

                System.out.println( "Bad server port input: "+port);

            }

            if (p != -1)

                isport = p;

        }

 

        init(primary,   // first or second server

             name,      // my name

             iport,     // my port

             sname,     // other server's name

             shost,     // other server's hostname

             isport,    // other server's port

             smessage,  // msg for other server

             clientServer); // whether to run as initiator with own creds

    }

 

    private void duplicateOptionError(String option) {

        System.out.println("Duplicate option: " + option);

        printUsage();

        System.exit(1);

    }

 

    private void noArgForOptionError(String option) {

        System.out.println("Missing argument for option: " + option);

        printUsage();

        System.exit(1);

    }

 

 

 

    void processRequests() throws Exception

    {

        ServerSocket ssocket = null;

        Server server = null;

        try {

            ssocket = new ServerSocket(myPort);

                do {

                    debug.out(Debug.OPTS_CAT_APPLICATION,

                     debugPrefix + " (" + myName + ")\n"

                        + "\tlistening on port " + myPort + " ...");

 

                Socket csocket = ssocket.accept();

 

                    debug.out(Debug.OPTS_CAT_APPLICATION,

                   debugPrefix + "incoming connection on " + csocket);

 

                server = new Server(csocket); // set client socket per thread

                Thread thread = new Thread(server);

                  thread.start();

                if (!thread.isAlive())

                    server.dispose(); // close the client socket

                } while(true);

        } catch (Exception exc) {

                debug.out(Debug.OPTS_CAT_APPLICATION,

                debugPrefix + "*** ERROR processing requests ***");

                exc.printStackTrace();

        } finally {

            try {

                if (ssocket != null)

                        ssocket.close(); // close the server socket

                if (server != null)

                    server.dispose(); // close the client socket

            } catch (Exception exc) {}

        }

    }

 

    void dispose()

    {

        try {

            if (tcp != null)

            {

                tcp.close();

                tcp = null;

            }

        } catch (Exception exc) {}

    }

 

    boolean establishContext(GSSContext context) throws Exception

    {

        byte[] response = null;

        byte[] request  = null;

 

        debug.out(Debug.OPTS_CAT_APPLICATION,

                          debugPrefix + "establishing context");

 

        do {

            request = tcp.receive();

            if (request == null || request.length == 0)

            {

                debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                    + "Received no data; perhaps client disconnected");

 

                return false;

            }

 

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "accepting");

            debug.out(Debug.OPTS_CAT_APPLICATION, request);

            if (!useStreams) {

                response = context.acceptSecContext(

                                       request, 0, request.length);

            } else {

                ByteArrayOutputStream bos = new ByteArrayOutputStream();

                ByteArrayInputStream bis = null;

                bis = new ByteArrayInputStream(request);

                context.acceptSecContext(bis, bos);

                response = bos.toByteArray();

            }

 

            if (response != null) {

                 debug.out(Debug.OPTS_CAT_APPLICATION,

                           debugPrefix + "sending response");

                 tcp.send(response);

            }

        } while(!context.isEstablished());

 

        if (debug.on(Debug.OPTS_CAT_APPLICATION)) {

            String msg = "established context with initiator "

                                          + context.getSrcName();

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + msg);

 

            boolean delegationState = context.getCredDelegState();

            msg = "getCredDelegState=" + delegationState;

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + msg);

        }

 

        return true;

    }

 

    byte[] unwrap(GSSContext context, byte[] msg) throws Exception

    {

        debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "unwrapping");

 

        MessageProp mp = new MessageProp(true);

        byte[] unwrappedMsg = null;

        if (!useStreams) {

            unwrappedMsg = context.unwrap(msg, 0, msg.length, mp);

        } else {

            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            ByteArrayInputStream bis = new ByteArrayInputStream(msg);

            context.unwrap(bis, bos, mp);

            unwrappedMsg = bos.toByteArray();

        }

 

        debug.out(Debug.OPTS_CAT_APPLICATION,

                             debugPrefix + "unwrapped msg is:");

        debug.out(Debug.OPTS_CAT_APPLICATION, unwrappedMsg);

 

        return unwrappedMsg;

    }

 

    void verifyMIC (GSSContext context, byte[] mic, byte[] raw) throws Exception

    {

        debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "verifying MIC");

 

        MessageProp mp = new MessageProp(true);

        if (!useStreams) {

            context.verifyMIC(mic, 0, mic.length, raw, 0, raw.length, mp);

        } else {

            ByteArrayInputStream tokenBis = new ByteArrayInputStream(mic);

            ByteArrayInputStream msgBis = new ByteArrayInputStream(raw);

            context.verifyMIC(tokenBis, msgBis, mp);

        }

 

        debug.out(Debug.OPTS_CAT_APPLICATION,

                       debugPrefix + "successfully verified MIC");

    }

 

    void useDelegatedCred(GSSCredential delCred, String msg) throws Exception

    {

        if (delCred != null)

        {

            if (primaryServer)

            {

                debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix +

                        "Primary server received delegated cred; using it");

                runAsInitiator(delCred, msg); // using delegated creds

            }

            else

            {

                debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix +

                       "Non-primary server received delegated cred; "

                            + "ignoring it");

 

            }

        }

        else

        {

             debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix +

                                         "ERROR: null delegated cred");

        }

    }

 

    public void run()

    {

        byte[] response       = null;

        byte[] request        = null;

        boolean unwrapped     = false;

        GSSContext context    = null;

 

        try {

          Thread currentThread      = Thread.currentThread();

          String threadName   = currentThread.getName();

 

          debugPrefix = program + " " + threadName + ": ";

 

          debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                                 + "servicing client ...");

 

              debug.out(Debug.OPTS_CAT_APPLICATION,

              debugPrefix + "creating GSSContext");

 

          context = mgr.createContext(gssCred);

 

          // First establish context with the initiator.

          if (!establishContext(context))

              return;

 

          // Then process messages from the initiator.

          // We expect to receive a wrapped message followed by a MIC.

          // The MIC should have been calculated over the plain

          // text that we received wrapped.

          // Use delegated creds if any.

          // Then run as initiator using own creds if necessary; only

          // the first thread does this.

 

          do {

                  debug.out(Debug.OPTS_CAT_APPLICATION,

                  debugPrefix + "receiving per-message request");

 

              request = tcp.receive();

              if (request == null || request.length == 0)

              {

                      debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                     + "Received no data; perhaps client disconnected");

 

              return;

              }

             

              // Expect wrapped message first.

              if (!unwrapped)

              { 

                  response = unwrap(context, request);

                  unwrapped = true;

                  continue; // get next request

              }

 

              // Followed by a MIC.

              verifyMIC(context, request, response);

 

              // Impersonate the initiator if it delegated its creds to us.

              if (context.getCredDelegState()) {

                  GSSCredential delCred = context.getDelegCred();

                  useDelegatedCred(delCred, new String(response));

              }

 

              debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                  + "clientServer=" + clientServer

                  + ", beenInitiator=" + beenInitiator);

 

              // If necessary, run as initiator using our own creds.

              if (clientServer)

                  runAsInitiatorOnce(currentThread);

 

              debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "done");

              return;

 

          } while(true);

         

        } catch (Exception exc) {

                debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "ERROR");

            exc.printStackTrace();

 

            // Squelch per-thread exceptions so we don't bring

            // the server down because of exceptions in

            // individual threads.

            return;

        } finally {

            if (context != null)

            {

                try {

                    context.dispose();

                } catch (Exception exc) {}

            }

        }

    }

 

    synchronized void runAsInitiatorOnce(Thread thread)

        throws InterruptedException

    {

        if (!beenInitiator)

        {

            // set flag true early to prevent subsequent threads

            // from attempting to runAsInitiator.

            beenInitiator = true;

 

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix +

                    "About to run as initiator with own creds ...");

 

            //thread.sleep(30*1000, 0);

            runAsInitiator();

        }

    }

  

 

    void runAsInitiator(GSSCredential cred, String msg)

    {

        Client client = null;

        try {

            client = new Client(cred,

                                serviceNameNoRealm,

                                serviceHost,

                                servicePort,

                                msg == null ? serviceMsg : msg,

                                true); // use streams

   

            client.initialize();

 

            BitSet flags = new BitSet();

            flags.set(Util.CONTEXT_OPTS_MUTUAL);

            flags.set(Util.CONTEXT_OPTS_CONF);

            flags.set(Util.CONTEXT_OPTS_INTEG);

   

            client.interactWithAcceptor(flags);

 

        } catch (Exception exc) {

            debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

                  + "Exception running as initiator");

 

            exc.printStackTrace();

        } finally {

            try {

                client.dispose();

            } catch (Exception exc) {}

        }

    }

 

    void runAsInitiator()

    {

        if (clientServer)

        {

                debug.out(Debug.OPTS_CAT_APPLICATION,

               debugPrefix + "running as initiator with own creds");

 

            runAsInitiator(gssCred, serviceMsg); // use own creds, own message;

        }

        else

        {

                debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix

               + "Cannot run as initiator with own creds "

               + "\nbecause not running as both initiator and acceptor.");

        }

    }

 

    void printUsage()

    {

        System.out.println(program + usageString);

    }

 

    public static void main(String[] args) throws Exception

    {

        System.out.println(debug.toString()); // XXXXXXX

        String programName = "Server";

        try {

            Server server = new Server(programName,

                                       false); // don't use creds from Subject

            server.processArgs(args);

            server.initialize();

            server.processRequests();

        } catch (Exception exc) {

            debug.out(Debug.OPTS_CAT_APPLICATION, programName + ": EXCEPTION");

            exc.printStackTrace();

            throw exc;

        }

    }

}