For more information about using the sample client program, see Downloading and running the sample programs.
// IBM JGSS 1.0 Sample Client Program
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 client;
* to be used in conjunction with the JGSS sample server.
* The client first establishes a context with the server
* and then sends wrapped message followed by a MIC to the server.
* The MIC is calculated over the plain text that was wrapped.
* The client requires to server to authenticate itself
* (mutual authentication) during context establishment.
* It also delegates its credentials to the server.
*
* It sets the JAVA variable
* javax.security.auth.useSubjectCredsOnly to false
* so that JGSS will not acquire credentials through JAAS.
*
* The client 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.
*
* Usage: Client [options]
*
* The -? option produces a help message including supported options.
*
* This sample client does not use JAAS.
* The client can be run against the JAAS sample client and server.
* See {@link JAASClient JAASClient} for a sample client that uses JAAS.
*/
class Client
{
private Util testUtil = null;
private String myName = null;
private GSSName gssName = null;
private String serverName = null;
private int servicePort = 0;
private GSSManager mgr = GSSManager.getInstance();
private GSSName service = null;
private GSSContext context = null;
private String program = "Client";
private String debugPrefix = "Client: ";
private TCPComms tcp = null;
private String data = null;
private byte[] dataBytes = null;
private String serviceHostname= null;
private GSSCredential gssCred = null;
private static Debug debug = new Debug();
private static final String usageString =
"\t[-?] [-d | -n name] [-s serverName]"
+ "\n\t[-h serverHost [:port]] [-p port] [-m msg]"
+ "\n"
+ "\n -?\t\t\thelp; produces this message"
+ "\n -n name\t\tthe client's principal name (without realm)"
+ "\n -s serverName\t\tthe server's principal name (without realm)"
+ "\n -h serverHost[:port]\tthe server's hostname"
+ " (and optional port number)"
+ "\n -p port\t\tthe port on which the server will be listening"
+ "\n -m msg\t\tmessage to send to the server";
// Caller must call initialize (may need to call processArgs first).
public Client (String programName) throws Exception
{
testUtil = new Util();
if (programName != null)
{
program = programName;
debugPrefix = programName + ": ";
}
}
// Caller must call initialize (may need to call processArgs first).
Client (String programName, boolean useSubjectCredsOnly) throws Exception
{
this(programName);
setUseSubjectCredsOnly(useSubjectCredsOnly);
}
public Client(GSSCredential myCred,
String serverNameWithoutRealm,
String serverHostname,
int serverPort,
String message)
throws Exception
{
testUtil = new Util();
if (myCred != null)
{
gssCred = myCred;
}
else
{
throw new GSSException(GSSException.NO_CRED, 0,
"Null input credential");
}
init(serverNameWithoutRealm, serverHostname, serverPort, message);
}
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);
// 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(String myNameWithoutRealm,
String serverNameWithoutRealm,
String serverHostname,
int serverPort,
String message) throws Exception
{
myName = myNameWithoutRealm;
init(serverNameWithoutRealm, serverHostname, serverPort, message);
}
private void init(String serverNameWithoutRealm,
String serverHostname,
int serverPort,
String message) throws Exception
{
// peer's name
if (serverNameWithoutRealm != null)
{
this.serverName = serverNameWithoutRealm;
}
else
{
this.serverName = testUtil.getDefaultServicePrincipalWithoutRealm();
}
// peer's host
if (serverHostname != null)
{
this.serviceHostname = serverHostname;
}
else
{
this.serviceHostname = testUtil.getDefaultServiceHostname();
}
// peer's port
if (serverPort > 0)
{
this.servicePort = serverPort;
}
else
{
this.servicePort = testUtil.getDefaultServicePort();
}
// message for peer
if (message != null)
{
this.data = message;
}
else
{
this.data = "The quick brown fox jumps over the lazy dog";
}
this.dataBytes = this.data.getBytes();
tcp = new TCPComms(serviceHostname, servicePort);
}
void initialize() throws Exception
{
Oid krb5MechanismOid = new Oid("1.2.840.113554.1.2.2");
if (gssCred == null)
{
if (myName != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "creating GSSName USER_NAME for "
+ myName);
gssName = mgr.createName(
myName,
GSSName.NT_USER_NAME,
krb5MechanismOid);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Canonicalized GSSName=" + gssName);
}
else
gssName = null; // for default credentials
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "creating"
+ ((gssName == null)? " default " : " ")
+ "credential");
gssCred = mgr.createCredential(
gssName,
GSSCredential.DEFAULT_LIFETIME,
(Oid)null,
GSSCredential.INITIATE_ONLY);
if (gssName == null)
{
gssName = gssCred.getName();
myName = gssName.toString();
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "default credential principal=" + myName);
}
}
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + gssCred);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "creating canonicalized GSSName for serverName " + serverName);
service = mgr.createName(serverName,
GSSName.NT_HOSTBASED_SERVICE,
krb5MechanismOid);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Canonicalized server name = " + service);
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "Raw data=" + data);
}
void establishContext(BitSet flags) throws Exception
{
try {
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "creating GSScontext");
Oid defaultMech = null;
context = mgr.createContext(service, defaultMech, gssCred,
GSSContext.INDEFINITE_LIFETIME);
if (flags != null)
{
if (flags.get(Util.CONTEXT_OPTS_MUTUAL))
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting mutualAuthn");
context.requestMutualAuth(true);
}
if (flags.get(Util.CONTEXT_OPTS_INTEG))
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting integrity");
context.requestInteg(true);
}
if (flags.get(Util.CONTEXT_OPTS_CONF))
{
context.requestConf(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting confidentiality");
}
if (flags.get(Util.CONTEXT_OPTS_DELEG))
{
context.requestCredDeleg(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting delegation");
}
if (flags.get(Util.CONTEXT_OPTS_REPLAY))
{
context.requestReplayDet(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting replay detection");
}
if (flags.get(Util.CONTEXT_OPTS_SEQ))
{
context.requestSequenceDet(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting out-of-sequence detection");
}
// Add more later!
}
byte[] response = null;
byte[] request = null;
int len = 0;
boolean done = false;
do {
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Calling initSecContext");
request = context.initSecContext(response, 0, len);
if (request != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Sending initial context token");
tcp.send(request);
}
done = context.isEstablished();
if (!done)
{
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "Receiving response token");
byte[] temp = tcp.receive();
response = temp;
len = response.length;
}
} while(!done);
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "context established with acceptor");
} catch (Exception exc) {
exc.printStackTrace();
throw exc;
}
}
void doMIC() throws Exception
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "generating MIC");
byte[] mic = context.getMIC(dataBytes, 0, dataBytes.length, null);
if (mic != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "sending MIC");
tcp.send(mic);
}
else
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "getMIC Failed");
}
void doWrap() throws Exception
{
MessageProp mp = new MessageProp(true);
mp.setPrivacy(context.getConfState());
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "wrapping message");
byte[] wrapped = context.wrap(dataBytes, 0, dataBytes.length, mp);
if (wrapped != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "sending wrapped message");
tcp.send(wrapped);
}
else
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "wrap Failed");
}
void printUsage()
{
System.out.println(program + usageString);
}
void processArgs(String[] args) throws Exception
{
String port = null;
String myName = null;
int servicePort = 0;
String serviceHostname = null;
String sHost = null;
String msg = null;
GetOptions options = new GetOptions(args, "?h:p:m:n:s:");
int ch = -1;
while ((ch = options.getopt()) != options.optEOF)
{
switch(ch)
{
case '?':
printUsage();
System.exit(1);
case 'h':
if (sHost == null)
{
sHost = options.optArgGet();
int p = sHost.indexOf(':');
if (p != -1)
{
String temp1 = sHost.substring(0, p);
if (port == null)
port = sHost.substring(p+1, sHost.length()).trim();
sHost = temp1;
}
}
continue;
case 'p':
if (port == null)
port = options.optArgGet();
continue;
case 'm':
if (msg == null)
msg = options.optArgGet();
continue;
case 'n':
if (myName == null)
myName = options.optArgGet();
continue;
case 's':
if (serverName == null)
serverName = options.optArgGet();
continue;
}
}
if ((port != null) && (port.length() > 0))
{
int p = -1;
try {
p = Integer.parseInt(port);
} catch (Exception exc) {
System.out.println("Bad port input: "+port);
}
if (p != -1)
servicePort = p;
}
if ((sHost != null) && (sHost.length() > 0)) {
serviceHostname = sHost;
}
init(myName, serverName, serviceHostname, servicePort, msg);
}
void interactWithAcceptor(BitSet flags) throws Exception
{
establishContext(flags);
doWrap();
doMIC();
}
void interactWithAcceptor() throws Exception
{
BitSet flags = new BitSet();
flags.set(Util.CONTEXT_OPTS_MUTUAL);
flags.set(Util.CONTEXT_OPTS_CONF);
flags.set(Util.CONTEXT_OPTS_INTEG);
flags.set(Util.CONTEXT_OPTS_DELEG);
interactWithAcceptor(flags);
}
void dispose() throws Exception
{
if (tcp != null)
{
tcp.close();
}
}
public static void main(String args[]) throws Exception
{
System.out.println(debug.toString()); // XXXXXXX
String programName = "Client";
Client client = null;
try {
client = new Client(programName,
false); // don't use Subject creds.
client.processArgs(args);
client.initialize();
client.interactWithAcceptor();
} catch (Exception exc) {
debug.out(Debug.OPTS_CAT_APPLICATION,
programName + " Exception: " + exc.toString());
exc.printStackTrace();
throw exc;
} finally {
try {
if (client != null)
client.dispose();
} catch (Exception exc) {}
}
debug.out(Debug.OPTS_CAT_APPLICATION, programName + ": done");
}
}