to the caller of a per-message context method.
Parameters:
duplicate true if the token was a duplicate of an earlier token,
false otherwise
old true if the token's validity period has expired, false
otherwise
unseq true if a later token has already been processed,
false otherwise
gap true if one or more predecessor tokens have not yet
been successfully processed, false otherwise
minorStatus the integer minor status code that the underlying
mechanism wants to set
minorString the textual representation of the minorStatus
value
6.6. public class ChannelBinding
The GSS-API accommodates the concept of caller-provided channel
binding information. Channel bindings are used to strengthen the
quality with which peer entity authentication is provided during
context establishment. They enable the GSS-API callers to bind the
establishment of the security context to relevant characteristics
like addresses or to application specific data.
The caller initiating the security context must determine the
appropriate channel binding values to set in the GSSContext object.
The acceptor must provide an identical binding in order to validate
that received tokens possess correct channel-related characteristics.
Use of channel bindings is optional in GSS-API. Since channel-
binding information may be transmitted in context establishment
tokens, applications should therefore not use confidential data as
channel-binding components.
6.6.1. Constructors
public ChannelBinding(InetAddress initAddr, InetAddress acceptAddr,
byte[] appData)
Create a ChannelBinding object with user supplied address information
and data. "null" values can be used for any fields which the
application does not want to specify.
Parameters:
initAddr The address of the context initiator. "null" value
can be supplied to indicate that the application does
not want to set this value.
acceptAddrThe address of the context acceptor. "null" value can
be supplied to indicate that the application does not
want to set this value.
appData Application supplied data to be used as part of the
channel bindings. "null" value can be supplied to
indicate that the application does not want to set
this value.
public ChannelBinding(byte[] appData)
Creates a ChannelBinding object without any addressing information.
Parameters:
appData Application supplied data to be used as part of the
channel bindings.
6.6.2. getInitiatorAddress
public InetAddress getInitiatorAddress()
Returns the initiator's address for this channel binding. "null" is
returned if the address has not been set.
6.6.3. getAcceptorAddress
public InetAddress getAcceptorAddress()
Returns the acceptor's address for this channel binding. "null" is
returned if the address has not been set.
6.6.4. getApplicationData
public byte[] getApplicationData()
Returns application data being used as part of the ChannelBinding.
"null" is returned if no application data has been specified for the
channel binding.
6.6.5. equals
public boolean equals(Object obj)
Returns "true" if two channel bindings match. (Note that the Java
language specification requires that two objects that are equal
according to the equals(Object) method must return the same integer
result when the hashCode() method is called on them.)
Parameters:
obj Another channel binding to compare with.
6.7. public class Oid
This class represents Universal Object Identifiers (Oids) and their
associated operations.
Oids are hierarchically globally-interpretable identifiers used
within the GSS-API framework to identify mechanisms and name formats.
The structure and encoding of Oids is defined in ISOIEC-8824 and
ISOIEC-8825. For example the Oid representation of Kerberos V5
mechanism is "1.2.840.113554.1.2.2"
The GSSName name class contains public static Oid objects
representing the standard name types defined in GSS-API.
6.7.1. Constructors
public Oid(String strOid) throws GSSException
Creates an Oid object from a string representation of its integer
components (e.g. "1.2.840.113554.1.2.2").
Parameters:
strOid The string representation for the oid.
public Oid(InputStream derOid) throws GSSException
Creates an Oid object from its DER encoding. This refers to the full
encoding including tag and length. The structure and encoding of
Oids is defined in ISOIEC-8824 and ISOIEC-8825. This method is
identical in functionality to its byte array counterpart.
Parameters:
derOid Stream containing the DER encoded oid.
public Oid(byte[] DEROid) throws GSSException
Creates an Oid object from its DER encoding. This refers to the full
encoding including tag and length. The structure and encoding of
Oids is defined in ISOIEC-8824 and ISOIEC-8825. This method is
identical in functionality to its byte array counterpart.
Parameters:
derOid Byte array storing a DER encoded oid.
6.7.2. toString
public String toString()
Returns a string representation of the oid's integer components in
dot separated notation (e.g. "1.2.840.113554.1.2.2").
6.7.3. equals
public boolean equals(Object Obj)
Returns "true" if the two Oid objects represent the same oid value.
(Note that the Java language specification requires that two objects
that are equal according to the equals(Object) method must return the
same integer result when the hashCode() method is called on them.)
Parameters:
obj Another Oid object to compare with.
6.7.4. getDER
public byte[] getDER()
Returns the full ASN.1 DER encoding for this oid object, which
includes the tag and length.
6.7.5. containedIn
public boolean containedIn(Oid[] oids)
A utility method to test if an Oid object is contained within the
supplied Oid object array.
Parameters:
oids An array of oids to search.
6.8. public class GSSException extends Exception
This exception is thrown whenever a fatal GSS-API error occurs
including mechanism specific errors. It may contain both, the major
and minor, GSS-API status codes. The mechanism implementers are
responsible for setting appropriate minor status codes when throwing
this exception. Aside from delivering the numeric error code(s) to
the caller, this class performs the mapping from their numeric values
to textual representations. All Java GSS-API methods are declared
throwing this exception.
All implementations are encouraged to use the Java
internationalization techniques to provide local translations of the
message strings.
6.8.1. Static Constants
All valid major GSS-API error code values are declared as constants
in this class.
public static final int BAD_BINDINGS
Channel bindings mismatch error.
public static final int BAD_MECH
Unsupported mechanism requested error.
public static final int BAD_NAME
Invalid name provided error.
public static final int BAD_NAMETYPE
Name of unsupported type provided error.
public static final int BAD_STATUS
Invalid status code error - this is the default status value.
public static final int BAD_MIC
Token had invalid integrity check error.
public static final int CONTEXT_EXPIRED
Specified security context expired error.
public static final int CREDENTIALS_EXPIRED
Expired credentials detected error.
public static final int DEFECTIVE_CREDENTIAL
Defective credential error.
public static final int DEFECTIVE_TOKEN
Defective token error.
public static final int FAILURE
General failure, unspecified at GSS-API level.
public static final int NO_CONTEXT
Invalid security context error.
public static final int NO_CRED
Invalid credentials error.
public static final int BAD_QOP
Unsupported QOP value error.
public static final int UNAUTHORIZED
Operation unauthorized error.
public static final int UNAVAILABLE
Operation unavailable error.
public static final int DUPLICATE_ELEMENT
Duplicate credential element requested error.
public static final int NAME_NOT_MN
Name contains multi-mechanism elements error.
public static final int DUPLICATE_TOKEN
The token was a duplicate of an earlier token. This is a fatal error
code that may occur during context establishment. It is not used to
indicate supplementary status values. The MessageProp object is used
for that purpose.
public static final int OLD_TOKEN
The token's validity period has expired. This is a fatal error code
that may occur during context establishment. It is not used to
indicate supplementary status values. The MessageProp object is used
for that purpose.
public static final int UNSEQ_TOKEN
A later token has already been processed. This is a fatal error code
that may occur during context establishment. It is not used to
indicate supplementary status values. The MessageProp object is used
for that purpose.
public static final int GAP_TOKEN
An expected per-message token was not received. This is a fatal
error code that may occur during context establishment. It is not
used to indicate supplementary status values. The MessageProp object
is used for that purpose.
6.8.2. Constructors
public GSSException(int majorCode)
Creates a GSSException object with a specified major code.
Parameters:
majorCode The GSS error code causing this exception to be
thrown.
public GSSException(int majorCode, int minorCode, String minorString)
Creates a GSSException object with the specified major code, minor
code, and minor code textual explanation. This constructor is to be
used when the exception is originating from the security mechanism.
It allows to specify the GSS code and the mechanism code.
Parameters:
majorCode The GSS error code causing this exception to be
thrown.
minorCode The mechanism error code causing this exception
to be thrown.
minorString The textual explanation of the mechanism error
code.
6.8.3. getMajor
public int getMajor()
Returns the major code representing the GSS error code that caused
this exception to be thrown.
6.8.4. getMinor
public int getMinor()
Returns the mechanism error code that caused this exception. The
minor code is set by the underlying mechanism. Value of 0 indicates
that mechanism error code is not set.
6.8.5. getMajorString
public String getMajorString()
Returns a string explaining the GSS major error code causing this
exception to be thrown.
6.8.6. getMinorString
public String getMinorString()
Returns a string explaining the mechanism specific error code. null
will be returned when no mechanism error code has been set.
6.8.7. setMinor
public void setMinor(int minorCode, String message)
Used internally by the GSS-API implementation and the underlying
mechanisms to set the minor code and its textual representation.
Parameters:
minorCode The mechanism specific error code.
message A textual explanation of the mechanism error code.
6.8.8. toString
public String toString()
Returns a textual representation of both the major and minor status
codes.
6.8.9. getMessage
public String getMessage()
Returns a detailed message of this exception. Overrides
Throwable.getMessage. It is customary in Java to use this method to
obtain exception information.
7. Sample Applications
7.1. Simple GSS Context Initiator
import org.ietf.jgss.*;
/**
* This is a partial sketch for a simple client program that acts
* as a GSS context initiator. It illustrates how to use the Java
* bindings for the GSS-API specified in
* Generic Security Service API Version 2 : Java bindings
*
*
* This code sketch assumes the existence of a GSS-API
* implementation that supports the mechanism that it will need and
* is present as a library package (org.ietf.jgss) either as part of
* the standard JRE or in the CLASSPATH the application specifies.
*/
public class SimpleClient {
private String serviceName; // name of peer (ie. server)
private GSSCredential clientCred = null;
private GSSContext context = null;
private Oid mech; // underlying mechanism to use
private GSSManager mgr = GSSManager.getInstance();
...
...
private void clientActions() {
initializeGSS();
establishContext();
doCommunication();
}
/**
* Acquire credentials for the client.
*/
private void initializeGSS() {
try {
clientCred = mgr.createCredential(null /*default princ*/,
GSSCredential.INDEFINITE_LIFETIME /* max lifetime */,
mech /* mechanism to use */,
GSSCredential.INITIATE_ONLY /* init context */);
print("GSSCredential created for " +
cred.getName().toString());
print("Credential lifetime (sec)=" +
cred.getRemainingLifetime());
} catch (GSSException e) {
print("GSS-API error in credential acquisition: "
+ e.getMessage());
...
...
}
...
...
}
/**
* Does the security context establishment with the
* server.
*/
private void establishContext() {
byte[] inToken = new byte[0];
byte[] outToken = null;
try {
GSSName peer = mgr.createName(serviceName,
GSSName.NT_HOSTBASED_SERVICE);
context = mgr.createContext(peer, mech, gssCred,
GSSContext.INDEFINITE_LIFETIME/*lifetime*/);
// Will need to support confidentiality
context.requestConf(true);
while (!context.isEstablished()) {
outToken = context.initSecContext(inToken, 0,
inToken.length);
if (outToken != null)
writeGSSToken(outToken);
if (!context.isEstablished())
inToken = readGSSToken();
}
GSSName peer = context.getSrcName();
print("Security context established with " + peer +
" using underlying mechanism " + mech.toString());
} catch (GSSException e) {
print("GSS-API error during context establishment: "
+ e.getMessage());
...
...
}
...
...
}
/**
* Sends some data to the server and reads back the
* response.
*/
private void doCommunication() {
byte[] inToken = null;
byte[] outToken = null;
byte[] buffer;
// Container for multiple input-output arguments to and
// from the per-message routines (e.g., wrap/unwrap).
MessageProp messgInfo = new MessageProp();
try {
/*
* Now send some bytes to the server to be
* processed. They will be integrity protected but
* not encrypted for privacy.
*/
buffer = readFromFile();
// Set privacy to false and use the default QOP
messgInfo.setPrivacy(false);
outToken = context.wrap(buffer, 0, buffer.length,
messgInfo);
writeGSSToken(outToken);
/*
* Now read the response from the server.
*/
inToken = readGSSToken();
buffer = context.unwrap(inToken, 0, inToken.length,
messgInfo);
// All ok if no exception was thrown!
GSSName peer = context.getSrcName();
print("Message from " + peer.toString()
+ " arrived.");
print("Was it encrypted? " +
messgInfo.getPrivacy());
print("Duplicate Token? " +
messgInfo.isDuplicateToken());
print("Old Token? " +
messgInfo.isOldToken());
print("Unsequenced Token? " +
messgInfo.isUnseqToken());
print("Gap Token? " +
messgInfo.isGapToken());
...
...
} catch (GSSException e) {
print("GSS-API error in per-message calls: "
+ e.getMessage());
...
...
}
...
...
} // end of doCommunication method
...
...
} // end of class SimpleClient
7.2. Simple GSS Context Acceptor
import org.ietf.jgss.*;
/**
* This is a partial sketch for a simple server program that acts
* as a GSS context acceptor. It illustrates how to use the Java
* bindings for the GSS-API specified in
* Generic Security Service API Version 2 : Java bindings
*
* This code sketch assumes the existence of a GSS-API
* implementation that supports the mechanisms that it will need and
* is present as a library package (org.ietf.jgss) either as part of
* the standard JRE or in the CLASSPATH the application specifies.
*/
import org.ietf.jgss.*;
public class SimpleServer {
private String serviceName;
private GSSName name;
private GSSCredential cred;
private GSSManager mgr;
...
...
/**
* Wait for client connections, establish security contexts and
* provide service.
*/
private void loop() {
...
...
mgr = GSSManager.getInstance();
name = mgr.createName(serviceName,
GSSName.NT_HOSTBASED_SERVICE);
cred = mgr.createCredential(name,
GSSCredential.INDEFINITE_LIFETIME,
null,
GSSCredential.ACCEPT_ONLY);
// Loop infinitely
while (true) {
Socket s = serverSock.accept();
// Start a new thread to serve this connection
Thread serverThread = new ServerThread(s);
serverThread.start();
}
}
/**
* Inner class ServerThread whose run() method provides the
* secure service to a connection.
*/
private class ServerThread extends Thread {
...
...
/**
* Deals with the connection from one client. It also
* handles all GSSException's thrown while talking to
* this client.
*/
public void run() {
byte[] inToken = null;
byte[] outToken = null;
byte[] buffer;
GSSName peer;
// Container for multiple input-output arguments to and
// from the per-message routines (ie. wrap/unwrap).
MessageProp supplInfo = new MessageProp();
GSSContext secContext = null;
try {
// Now do the context establishment loop
GSSContext context = mgr.createContext(cred);
while (!context.isEstablished()) {
inToken = readGSSToken();
outToken = context.acceptSecContext(inToken, 0,
inToken.length);
if (outToken != null)
writeGSSToken(outToken);
}
// SimpleServer wants confidentiality to be
// available. Check for it.
if (!context.getConfState()){
...
...
}
GSSName peer = context.getSrcName();
Oid mech = context.getMech();
print("Security context established with " +
peer.toString() +
" using underlying mechanism " +
mech.toString() +
" from Provider " +
context.getProvider().getName());
// Now read the bytes sent by the client to be
// processed.
inToken = readGSSToken();
// Unwrap the message
buffer = context.unwrap(inToken, 0, inToken.length,
supplInfo);
// All ok if no exception was thrown!
// Print other supplementary per-message status
// information
print("Message from " +
peer.toString() + " arrived.");
print("Was it encrypted? " +
supplInfo.getPrivacy());
print("Duplicate Token? " +
supplInfo.isDuplicateToken());
print("Old Token? " + supplInfo.isOldToken());
print("Unsequenced Token? " +
supplInfo.isUnseqToken());
print("Gap Token? " + supplInfo.isGapToken());
/*
* Now process the bytes and send back an encrypted
* response.
*/
buffer = serverProcess(buffer);
// Encipher it and send it across
supplInfo.setPrivacy(true); // privacy requested
supplInfo.setQOP(0); // default QOP
outToken = context.wrap(buffer, 0, buffer.length,
supplInfo);
writeGSSToken(outToken);
} catch (GSSException e) {
print("GSS-API Error: " + e.getMessage());
// Alternatively, could call e.getMajorMessage()
// and e.getMinorMessage()
print("Abandoning security context.");
...
...
}
...
...
} // end of run method in ServerThread
} // end of inner class ServerThread
...
...
} // end of class SimpleServer
8. Security Considerations
The Java language security model allows platform providers to have
policy based fine-grained access control over any resource that an
application wants. When using a Java security manager (such as, but
not limited to, the case of applets running in browsers) the
application code is in a sandbox by default.
Administrators of the platform JRE determine what permissions, if
any, are to be given to source from different codebases. Thus the
administrator has to be aware of any special requirements that the
GSS provider might have for system resources. For instance, a
Kerberos provider might wish to make a network connection to the KDC
to obtain initial credentials. This would not be allowed under the
sandbox unless the administrator had granted permissions for this.
Also note that this granting and checking of permissions happens
transparently to the application and is outside the scope of this
document.
The Java language allows administrators to pre-configure a list of
security service providers in the <JRE>/lib/security/java.security
file. At runtime, the system approaches these providers in order of
preference when looking for security related services. Applications
have a means to modify this list through methods in the "Security"
class in the "java.security" package. However, since these
modifications would be visible in the entire JVM and thus affect all
code executing in it, this operation is not available in the sandbox
and requires special permissions to perform. Thus when a GSS
application has special needs that are met by a particular security
provider, it has two choices:
1) To install the provider on a JVM wide basis using the
java.security.Security class and then depend on the system to
find the right provider automatically when the need arises.
(This would require the application to be granted a
"insertProvider SecurityPermission".)
2) To pass an instance of the provider to the local instance of
GSSManager so that only factory calls going through that
GSSManager use the desired provider. (This would not require
any permissions.)
9. Acknowledgments
This proposed API leverages earlier work performed by the IETF's CAT
WG as outlined in both RFC2743 and RFC2744. Many conceptual
definitions, implementation directions, and explanations have been
included from these documents.
We would like to thank Mike Eisler, Lin Ling, Ram Marti, Michael
Saltz and other members of Sun's development team for their helpful
input, comments and suggestions.
We would also like to thank Joe Salowey, and Michael Smith for many
insightful ideas and suggestions that have contributed to this
document.
10. Bibliography
[GSSAPIv2] Linn, J., "Generic Security Service Application
Program Interface, Version 2", RFC2078, January
1997.
[GSSAPIv2-UPDATE] Linn, J., "Generic Security Service Application
Program Interface, Version 2, Update 1", RFC2743,
January 2000.
[GSSAPI-Cbind] Wray, J., "Generic Security Service API Version 2 :
C-bindings", RFC2744, January 2000.
[KERBV5] Linn, J., "The Kerberos Version 5 GSS-API
Mechanism", RFC1964, June 1996.
[SPKM] Adams, C., "The Simple Public-Key GSS-API
Mechanism", RFC2025, October 1996.
11. Authors' Addresses
Address comments related to this memorandum to:
<cat-ietf@mit.edu>
Jack Kabat
ValiCert, Inc.
339 N. Bernardo Avenue
Mountain View, CA
94043, USA
Phone: +1-650-567-5496
EMail: jackk@valicert.com
Mayank Upadhyay
Sun Microsystems, Inc.
901 San Antonio Road, MS CUP02-102
Palo Alto, CA 94303
Phone: +1-408-517-5956
EMail: mdu@eng.sun.com
12. Full Copyright Statement
Copyright (C) The Internet Society (2000). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Acknowledgement
Funding for the RFCEditor function is currently provided by the
Internet Society.