This part shows you how to build applications that
perform secure communications. The Java SE 6 platform provides three
standard APIs that allow applications to perform secure
communications: The Java Generic Security Service (GSS), the Java SASL API,
and the Java Secure Socket Extension (JSSE). When building an application,
which of these APIs should you use? The answer
depends on many factors, including requirements of the protocol or
service, deployment infrastructure, and integration with other
security services. For example, if you are building an LDAP client
library, you would need to use the Java SASL API because use of SASL
is part of LDAP's protocol definition. As an other example, if the
service supports SSL, then the client application attempting to access
the service would need to use JSSE.
Exercise 3: Using the Java Generic
Security Service (GSS) API
Goal of this exercise:
The goal of this exercise is to learn how to use the Java GSS API
to perform secure authentication and communication.
Background
for this exercise:
The
Generic Security
Service API provides a uniform C-language interface to access various
security services, such as authentication, message integrity, and
message confidentiality. The Java GSS API provides the corresponding
interface for Java applications. It allows applications to
perform
authentication and establish secure communication with the peer. One of
the most common security service accessed via the GSS-API and Java
GSS-API is Kerberos.
This exercise
is a client-server application that demonstrates how to communicate
securely using the Java GSS API. The client and server parts first
authenticate to Kerberos, as shown in
Exercise 1. This stores the credentials in the
subject.
The application then executes an action that performs Java GSS
operations (with Kerberos as the underlying GSS mechanism)
inside of a Subject.doAs using the subject.
The Java GSS Kerberos mechanism, because it is
executing inside the doAs, obtains the Kerberos credentials
from the subject, and uses them to authenticate with the peer
and to exchange messages securely.
This code fragment defines the action to execute after the
service principal has authenticated to the KDC. It replaces the MyAction
of line 11 of Exercise 1. Note the highlighted
lines. The code first creates an instance of GSSManager
[line 8], which it uses to obtain its own credentials [line 10-11] and
to create an instance of GSSContext [line 18]. It
uses this context to perform authentication [the loop between lines
22-34]. Upon completing authentication, it accepts encrypted input from
the client and uses the established security context to decrypt the
data [line 45]. It then uses the security context to encrypt
a reply containing the original input and the date [line 49], and then
sends it back to the client.
Code listing for GssServer.java.
static class GssServerAction implements
PrivilegedExceptionAction {
...
public Object run() throws Exception {
// Create server socket for
accepting connections
ServerSocket ss = new
ServerSocket(localPort);
// Get own Kerberos
credentials for accepting connection
This code fragment defines the action to execute after the client
principal has authenticated to the KDC. It replaces the MyAction
of line 11 of Exercise 1. Note the highlighted
lines. The code first creates an instance of GSSManager
[line 10], which it uses to obtain a principal name for the service
that
it is going to communicate with [line 12]. It then creates an instance
of GSSContext [line 15,16] to perform
authentication [the loop between lines 22-33] with the service. Upon
completing authentication, it uses the established security context
to encrypt a message [line 42] and sends it to the server.
It then reads an encrypted message from the server and
decodes it using the established security context [line 53].
Code listing for GssClient.java.
static class GssClientAction implements
PrivilegedExceptionAction {
...
public Object run() throws Exception {
// Create socket to server
Socket socket = new
Socket(hostName, port);
DataInputStream inStream =
new DataInputStream(socket.getInputStream());
DataOutputStream outStream =
new DataOutputStream(socket.getOutputStream());
Run the client application. GssClient takes two
parameters: the service name and the name of the server that the
service
is running on. For example, if the service is host
running on the machine j1hol-001, you would
enter the following. When prompted for the password, enter changeit.
Received message: Hello There! Thu May 06 12:11:15
PDT 2005
Summary:
In this exercise, you learned how to
write a client-server application that uses the Java GSS API to
authenticate and communicate securely with each other.
Next Steps
Proceed to Exercise 4 to learn how to write a client/server application that uses the Java SASL API to authenticate and communicate securely with each other.
Proceed to Exercise 5 to learn how to write a client/server application that uses the JSSE to authenticate and communicate securely with each other.
Proceed to Exercise 6 to learn how to
configure the sample programs that you have just used to achieve single sign-on in a Kerberos environment.
Exercise 4: Using the Java SASL API
Goal of this exercise:
The goal of this exercise is to learn how to use the Java SASL API to perform secure authentication and communication.
Background for this exercise:
Simple Authentication
and Security Layer (SASL) specifies a challenge-response protocol in which data is exchanged between the client and the server for the
purposes of authentication and (optional) establishment of a security
layer on which to carry on subsequent communications. SASL allows
different mechanisms to be used; each such mechanism is
identified by a profile that defines the data to be exchanged and a
name. SASL is used with connection-based protocols such as LDAPv3 and
IMAPv4. SASL is described in RFC 4422.
The Java SASL API defines an API for applications to use SASL in a
mechanism-independent way. For example, if you are writing a library
for a networking protocol that uses SASL, you can use the Java SASL API
to generate the data to be exchanged with the peer. When the library is
deployed, you can dynamically configure the mechanisms to use with the
library.
In addition to authentication, you can use SASL to negotiate a
security layer to be used after authentication. But unlike the GSS-API, the
properties of the security layer (such as whether you want integrity or
confidentiality) is decided at negotiation time. (the GSS-API allows
confidentiality to be turned on or off per message).
This exercise
is a client-server application that demonstrates how to communicate
securely using the Java SASL API. The client and server parts first
authenticate to Kerberos using
Exercise 1. This stores the credentials in the
subject.
The application then executes an action that performs Java SASL API
operations (with Kerberos as the underlying SASL mechanism)
inside of a Subject.doAs using the subject.
The SASL/Kerberos mechanism, because it is
executing inside the doAs, obtains the Kerberos credentials
from the subject, and uses them to authenticate with the peer
and to exchange messages securely.
This example uses a simple protocol implemented by the AppConnection class.
This protocol exchanges authentication commands and data commands.
Each command consists of a type (e.g., AppConnection.AUTH_CMD),
the length of the data to follow, and the data itself. The data is a
SASL buffer if it is for authentication or
encrypted/integrity-protected application data; it is plain application
data
otherwise.
This code fragment defines the action to execute after the
service principal has authenticated to the KDC. It replaces the MyAction
of line 11 of Exercise 1. Note the highlighted
lines. The server specifies the quality-of-protections that it will
support
[line 9] and then creates an instance of SaslServer to
perform
the authentication [line 21]. The challenge-response protocol of SASL
is
performed in the while loop [lines 33-49], with
the server sending challenges to the client and processing the
responses from
the client.
After authentication, the identity of the authenticated client
can be obtained via a call to getAuthorizedID() [line
61].
If a security layer was negotiated, the server can exchange data
securely
with the client [lines 66,70].
Code listing for SaslTestServer.java.
static class SaslServerAction implements
PrivilegedExceptionAction {
...
public Object run() throws Exception {
// Create server socket for
accepting connections
ServerSocket ss = new
ServerSocket(localPort);
// Support all
quality-of-protection options
HashMap<String,Object>
props = new HashMap<String,Object>();
props.put(Sasl.QOP,
"auth-conf,auth-int,auth");
while (true) {
// Create
application-level connection to handle request
Socket socket =
ss.accept();
AppConnection
conn = new AppConnection(socket);
// Normally, the
application protocol will negotiate which
// SASL mechanism
to use. In this simplified example, we
// will always
use "GSSAPI" (the name of the mechanism that does Kerberos via GSS-API)
Read the following code. This is located in src/SaslTestClient.java.
This code fragment defines the action to execute after the client
principal has authenticated to the KDC. It replaces the MyAction
of line 11 of Exercise 1. Note the highlighted
lines. The program first specifies the quality of protection
that it wants (in this case, confidentiality) [line 8] and
then creates an instance of SaslClient to use for
authentication [lines 11-12].
It then checks whether the mechanism has an initial response and if so,
gets the response by invoking evaluateChallenge()
with an empty byte array [line 20].
It then sends the response to the server to begin the authentication.
The challenge-response protocol of SASL is
performed in the while loop [lines 24-39], with
the client evaluating the challenges that it gets from the server
and sending the server the corresponding responses to the challenges.
After authentication, the client can proceed to communicate with the
server using the negotiated security layer [lines 48,55].
Code listing for SaslTestClient.java.
static class SaslClientAction implements
PrivilegedExceptionAction {
...
public Object run() throws Exception {
// Create application-level
connection
AppConnection conn = new
AppConnection(serverName, port);
HashMap<String,Object>
props = new HashMap<String,Object>();
Launch a new window and start the server. SaslTestServer
takes two
parameters: the service name and the name of the server that the
service
is running on. For example, if the service is host
running on the machine j1hol-001, you would
enter the following.
Run the client application. SaslTestClient takes two
parameters: the service name and the name of the server that the
service
is running on. For example, if the service is host
running on the machine j1hol-001, you would
enter the following. When prompted for the password, enter changeit.
Received: Hello There! Fri May 07 15:32:37 PDT 2005
To try the program using different quality-of-protection, change
line 8 in SaslTestClient. For example, replace line 8
with the following line to use integrity protection on (no
confidentiality).
props.put(Sasl.QOP, "auth-int");
Summary:
In this exercise, you learned how to
write a client-server application that uses the Java SASL API to
authenticate and communicate securely with each other.
Next Steps
Proceed to Exercise 5 to learn how to write
a
client/server application that uses the JSSE to authenticate and
communicate securely with each other.
Proceed to Exercise 6 to learn how to
configure the sample programs that you have just used to achieve single
sign-on in a Kerberos environment.
Exercise 5: Using the Java Secure
Socket Extension with Kerberos
Goal
of this exercise:
The goal of this exercise is to learn how to use the JSSE API
to perform secure authentication and communication using Kerberos cipher suites.
Background
for this exercise:
Secure
Socket Layer (SSL) and Transport Layer Security (TLS) are the
most widely used protocols for implementing cryptography on the
Internet. TLS is the Internet standard evolved from SSL. SSL/TLS
provides application-level protocols (such as HTTP and LDAP) with
secure authentication and communication. For example, HTTPS is the
resulting protocol of using HTTP over SSL/TLS.
SSL/TLS is used not only for
standard protocols such as HTTP, it is also widely used when building
custom applications using custom protocols that need to communicate
securely.
SSL/TLS traditionally used certificate-based authentication and is
commonly used for server-authentication. For example, when a Web
client such as a browser accesses a secure Web site (server) on behalf
of a user, the server sends its certificate to the browser so that the
browser can verify the identity of the server. This ensures
that the user does
not divulge confidential information (such as credit card information)
to a bogus server. Recently, a new standard allows the use of Kerberos
with TLS. This means instead of using certificate-based
authentication, an application can use Kerberos credentials and take
advantage of the Kerberos infrastructure in the deployment
environment. Using Kerberos cipher suites also provides automatic
support for mutual authentication in which the client is also
authenticated in addition to the server.
The decision of whether to use Java GSS, Java SASL, or JSSE for a
particular application often depends upon several factors, including
(the protocols being used by) the services with
which the application interacts, the deployment environment (PKI or
Kerberos-based), and the application's security requirements.
JSSE provides a secure end-to-end channel that takes care of the I/O
and transport, while Java GSS and Java SASL provide encryption
and integrity-protection on the data, but the application is
responsible for transporting the secured data to its peer.
Some details about factors for deciding when to use JSSE versus
Java GSS are presented in the document,
When
to use Java GSS vs. JSSE.
This exercise
is a client-server application that demonstrates how to communicate
securely using the JSSE and Kerberos cipher suites.
The client and server parts first authenticate to Kerberos using
Exercise 1. This stores the credentials in the
subject.
The application then executes an action that performs JSSE
operations (using a Kerberos cipher suite)
inside of a Subject.doAs using the subject.
The Kerberos cipher suite implementation, because it is
executing inside the doAs, obtains the Kerberos credentials
from the subject, and uses them to authenticate with the peer
and to exchange messages securely.
This example sends newline-terminated messages, encrypted using
the negotiated cipher suite and integrity-protected,
back and forth between client and server.
According to the standard (RFC 2712)
all Kerberos-enabled TLS applications use the same service name,
namely,
"host". That is why in this exercise, you do not need to
explicitly
supply the Kerberos service name.
This code fragment defines the action to execute after the
service principal has authenticated to the KDC. It replaces the MyAction
of line 11 of Exercise 1. Note the highlighted
lines. The server first creates an SSLServerSocket
[lines 5-8]. This is analogous to an application creating a plain ServerSocket
except an SSLServerSocket will
provide
automatic authentication, encryption and decryption, as needed.
The server then sets the cipher suites that it wants to use [lines
11-12]. The server then runs in a loop, accepting
connections from SSL clients [line 17], and reads and writes from
the SSL socket [lines 23, 28]. The server can find out the identities
of the
owners of socket by invoking the getLocalPrincipal()
and getPeerPrincipal() methods [lines
32-33].
Code listing for JsseServer.java.
static class JsseServerAction implements
PrivilegedExceptionAction {
// Get names of
principal at both ends of secure connection
Principal
self = sslSocket.getSession().getLocalPrincipal();
Principal
peer = sslSocket.getSession().getPeerPrincipal();
sslSocket.close();
}
}
}
Compile the sample code.
% javac JsseServer.java
Read the following code. This is located in src/JsseClient.java.
This code fragment defines the action to execute after the client
principal has authenticated to the KDC. It replaces the MyAction
of line 11 of Exercise
1. Note the highlighted lines. The client first creates an SSLSocket.
The client then sets the
cipher
suites that it wants to use [lines 11-12]. The client then exchanges
messages with the server using the SSLSocket by reading and
writing to the socket's
input/output
streams. The client can find out the identities of the
owners of socket by invoking the getLocalPrincipal()
and getPeerPrincipal() methods [lines
26-27].
Code listing for JsseClient.java
static class JsseClientAction implements
PrivilegedExceptionAction {
// Should handle exception if
enabledSuites is not supported
BufferedReader in = new
BufferedReader(new InputStreamReader(
sslSocket.getInputStream()));
BufferedWriter out = new
BufferedWriter(new OutputStreamWriter(
sslSocket.getOutputStream()));
String outStr = ...;
out.write(outStr);
out.flush();
String inStr = in.readLine();
// ... use inStr
// Get names of principal at
both ends of secure connection
Principal self =
sslSocket.getSession().getLocalPrincipal();
Principal peer =
sslSocket.getSession().getPeerPrincipal();
sslSocket.close();
return null;
}
}
Compile the sample code.
% javac JsseClient.java
Launch a new window and start the server. JsseServer
takes one
parameter: the name of the server that the JSSE service
is running on. For example, if it is
running on the machine j1hol-001, you would
enter the following.
Run the client application. JsseClient takes one
parameter: the name of the server that the JSSE service
is running on. For example, if the service is
running on the machine j1hol-001, you would
enter the following. When prompted for a password, enter changeit.
Received: Hello There! Fri May 07 15:32:37 PDT 2005
Cipher suite in use: TLS_KRB5_WITH_3DES_EDE_CBC_SHA
I am: test@J1LABS.EXAMPLE.COM
Server is: host/j1hol-001@J1LABS.EXAMPLE.COM
Summary:
In this exercise, you learned how to
write a client-server application that uses JSSE to
authenticate and communicate securely with each other, using Kerberos
as the underlying authentication system.
Next Steps
Proceed to Exercise 6 to learn how to
configure the sample programs in Exercises 3, 4, and 5 to achieve
single
sign-on in a Kerberos environment.