Re: GSSException: Failure unspecified at GSS-API level (Mechanismbytes long)



Hey, thanks for the response. I'm sorry it's taken me so long to get
back to you but I sort of sidelined this problem for a little while.
Here is the stack trace of the error I'm receiving:

GSSException: Failure unspecified at GSS-API level (Mechanism level:
Could not use DES Cipher - Output buffer must be (at least) 16 bytes
long)
at
sun.security.jgss.krb5.MessageToken.getDesCbcChecksum(MessageToken.java:530)
at
sun.security.jgss.krb5.MessageToken.getChecksum(MessageToken.java:453)
at
sun.security.jgss.krb5.MessageToken.verifySignAndSeqNumber(MessageToken.java:325)
at
sun.security.jgss.krb5.WrapToken.getDataFromBuffer(WrapToken.java:269)
at sun.security.jgss.krb5.WrapToken.getData(WrapToken.java:198)
at sun.security.jgss.krb5.WrapToken.getData(WrapToken.java:171)
at sun.security.jgss.krb5.Krb5Context.unwrap(Krb5Context.java:876)
at sun.security.jgss.GSSContextImpl.unwrap(GSSContextImpl.java:362)
at
edu.bu.rcs.objects.security.SecurityContext.unwrap(SecurityContext.java:186)
at edu.bu.rcs.legend.client.Client.issueCommand(Client.java:184)
at edu.bu.rcs.legend.client.Client.issueCommand(Client.java:153)
at edu.bu.rcs.legend.client.Client$1.run(Client.java:289)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:437)
at
edu.bu.rcs.objects.security.SecurityContext.doAsPrivileged(SecurityContext.java:334)
at edu.bu.rcs.legend.client.Client.login(Client.java:281)
at
edu.bu.rcs.legend.gui.main.MainWindowPanel$3.run(MainWindowPanel.java:381)

This problem only occurs when the server is being run using java 1.5
and I connect from a client using java 1.4 or vice versa. I'm not sure
how to go about configuring to use the DES encryption type as you had
mentioned. I created a special SecurityContext class which both the
client and server use and simplifies the login/encryption/decryption
process for the client and server. Essentially, on startup, the server
logins into the SecurityContext object (using its login function) as a
Kerberos principal server. On startup, the client logins into the
SecurityContext object as a Kerberos principal user. The client then
using SecurityContext's initSecContext to initialize a GSSContext to
the Kerberos principal server, which the server later accepts using the
acceptSecContext method. Finally, wrap and unwrap are used to
encrypt/decrypt messages passed back and forth.

Both client and server have the following code in the main functions:
URL config = Client.class.getResource("jaas.conf");
System.setProperty("java.security.auth.login.config", config
.toExternalForm());

String krb5Realm = "bu.edu";
System.setProperty("java.security.krb5.realm", krb5Realm);

String krb5Kdc = "kerberos1.bu.edu";
System.setProperty("java.security.krb5.kdc", krb5Kdc);

I did this so I wouldn't have to pass this information as vm arguments.

The client jaas file looks like:
Client {
com.sun.security.auth.module.Krb5LoginModule required;
};
The server jaas file looks like:
Server {
com.sun.security.auth.module.Krb5LoginModule required storeKey=true;
};


public class SecurityContext implements CallbackHandler {

protected GSSContext context = null;

protected LoginContext lc = null;

protected String service = null;

protected String username;

protected char[] password;

public SecurityContext() {

}

public void setServiceName(String service) {
this.service = service;
}

public boolean login(String loginContext, String username, char[]
password) {
this.username = username;
this.password = password;

lc = null;
try {
lc = new LoginContext(loginContext, this);
} catch (LoginException le) {
System.err
.println("Cannot create LoginContext. " +
le.getMessage());
System.exit(-1);
} catch (SecurityException se) {
System.err
.println("Cannot create LoginContext. " +
se.getMessage());
System.exit(-1);
}

int i;
for (i = 0; i < 3; i++) {
try {
lc.login();
return true;

} catch (AccountExpiredException aee) {

System.err.println("Your account has expired. "
+ "Please notify your administrator.");
System.exit(-1);

} catch (CredentialExpiredException cee) {

System.err.println("Your credentials have expired.");
System.exit(-1);

} catch (FailedLoginException fle) {

System.err.println("Authentication Failed");
try {
Thread.sleep(3000);
} catch (Exception e) {
// ignore
}

} catch (Exception e) {

//System.err.println("Unexpected Exception - unable to
continue");
//e.printStackTrace();
return false;
}
}

// did they fail three times?
if (i == 3) {
System.err.println("Sorry");
}

return false;
}

public byte[] acceptSecContext(byte[] token) {
try {
GSSManager manager = GSSManager.getInstance();
context = manager.createContext((GSSCredential) null);

while (!context.isEstablished()) {

/*
* Create a GSSContext to receive the incoming request
from the
* client. Use null for the server credentials passed
in. This
* tells the underlying mechanism to use whatever
credentials it
* has available that can be used to accept this
connection.
*/

token = context.acceptSecContext(token, 0,
token.length);

if (token != null)
return token;

}
} catch (GSSException e) {
e.printStackTrace();
}

return token;
}

public synchronized byte[] wrap(Object object) {
/*
* The first MessageProp argument is 0 to request the default
* Quality-of-Protection. The second argument is true to
request privacy
* (encryption of the message).
*/
MessageProp prop = new MessageProp(0, true);

/*
* Encrypt the data and send it across. Integrity protection is
always
* applied, irrespective of confidentiality (i.e., encryption).
You can
* use the same token (byte array) as that used when
establishing the
* context.
*/

byte[] token = null;

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] messageBytes = baos.toByteArray();
token = context.wrap(messageBytes, 0, messageBytes.length,
prop);

oos.close();
baos.close();
} catch (IOException e) {
e.printStackTrace();
} catch (GSSException e) {
e.printStackTrace();
}

return token;
}

public synchronized Object unwrap(byte[] token) {
MessageProp prop = new MessageProp(0, true);

Object object = null;
try {
token = context.unwrap(token, 0, token.length, prop);

ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(token));

object = ois.readObject();

ois.close();
} catch (GSSException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

return object;
}

public byte[] initSecContext(byte[] token) {
try {
if (context == null) {
/*
* This Oid is used to represent the Kerberos version 5
GSS-API
* mechanism. It is defined in RFC 1964. We will use
this Oid
* whenever we need to indicate to the GSS-API that it
must use
* Kerberos for some purpose.
*/

Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");

GSSManager manager = GSSManager.getInstance();

/*
* Create a GSSName out of the server's name. The null
indicates
* that this application does not wish to make any
claims about
* the syntax of this name and that the underlying
mechanism
* should try to parse it as per whatever default
syntax it
* chooses.
*/
GSSName serverName = manager.createName(service, null);

/*
* Create a GSSContext for mutual authentication with
the
* server. - serverName is the GSSName that represents
the
* server. - krb5Oid is the Oid that represents the
mechanism to
* use. The client chooses the mechanism to use. - null
is
* passed in for client credentials - DEFAULT_LIFETIME
lets the
* mechanism decide how long the context can remain
valid. Note:
* Passing in null for the credentials asks GSS-API to
use the
* default credentials. This means that the mechanism
will look
* among the credentials stored in the current Subject
to find
* the right kind of credentials that it needs.
*/
context = manager.createContext(serverName, krb5Oid,
null,
GSSContext.DEFAULT_LIFETIME);

// Set the desired optional features on the context.
The client
// chooses these options.

context.requestMutualAuth(true); // Mutual
authentication
//context.requestConf(true); // Will use
confidentiality later
//context.requestInteg(true); // Will use integrity
later

}

// token is ignored on the first call
if (token == null)
token = new byte[0];
token = context.initSecContext(token, 0, token.length);
} catch (GSSException e) {
e.printStackTrace();
}

return token;
}

public void dispose() {
if (context != null)
try {
context.dispose();
} catch (GSSException e) {
e.printStackTrace();
}
}

public void logout() {
if (lc != null) {
try {
lc.logout();
} catch (LoginException e) {
e.printStackTrace();
}
lc = null;
}
}

public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof TextOutputCallback) {

// display the message according to the specified type
TextOutputCallback toc = (TextOutputCallback)
callbacks[i];
switch (toc.getMessageType()) {
case TextOutputCallback.INFORMATION:
break;
case TextOutputCallback.ERROR:
break;
case TextOutputCallback.WARNING:
break;
default:
throw new IOException("Unsupported message type: "
+ toc.getMessageType());
}

} else if (callbacks[i] instanceof NameCallback) {

// prompt the user for a username
NameCallback nc = (NameCallback) callbacks[i];

nc.setName(username);

} else if (callbacks[i] instanceof PasswordCallback) {

// prompt the user for sensitive information
PasswordCallback pc = (PasswordCallback) callbacks[i];

pc.setPassword(password);

} else {
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
}
}

public Subject getSubject() {
if (lc != null)
return lc.getSubject();

return null;
}

public Object doAsPrivileged(PrivilegedAction action) {
if (lc != null)
return Subject.doAsPrivileged(lc.getSubject(), action,
null);

return null;
}

public boolean isEstablished() {
if (context == null)
return false;
return context.isEstablished();
}

public String getUsername() {
try {
GSSName name = context.getSrcName();
if (name != null)
return name.toString();
} catch (GSSException e) {

}
return null;
}

}

I think that should hopefully be all the information you will need.
Thanks in advance.
Andrew

.



Relevant Pages

  • Re: Socket problems
    ... I'm trying to write a 20 client chat server which is not ... >> public void listenFromClients() ... > // create a new communicator task and pass it the socket ...
    (comp.lang.java.programmer)
  • Remoting Error
    ... can the server application call methods of the shared Object?? ... public RemDeskBridge rdb; ... The procedure on client side is:- ... public void setUP ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Multiplayer gaming
    ... Server code: ... public void RunServer() { ... Client client = new Client); ... We have a very simple game with several spaceships which try to kill ...
    (microsoft.public.dotnet.csharp.general)
  • GSSException: Failure unspecified at GSS-API level (Mechanism level: Could not use DES Cipher &#
    ... communication between a client and server application. ... and I connect from a client using java 1.4 or vice versa. ... I created a special SecurityContext class which both the ... GSSException: Failure unspecified at GSS-API level (Mechanism level: ...
    (comp.protocols.kerberos)
  • Deserialization exception when using MarshalByRef object with events
    ... I'm getting the following exception on the client when attempting to ... of code from the server, client, MarshalByRef object, and .config ... public void Start ... public event BombHandler BombDetonated; ...
    (microsoft.public.dotnet.framework.remoting)