Summary |  Admin |  Home Page |  Forums |  Tracker |  Bugs |  Support |  Patches |  RFE |  Lists |  Tasks |  Docs |  News |  CVS |  Files |

Contents



Overview

JPAM is a Java-PAM bridge.  PAM, or Pluggable Authentication Modules, is a standard security architecture used on Unix, Linux and Mac OS X systems.

JPAM permits the use of PAM authentication facilities by Java applications running on those platforms.

These facilities include:
Jpam is a Java-PAM bridge.

JPAM has its own proprietary API via the PAM class but also supports JAAS.

PAM

PAM, or Pluggable Authentication Modules, is the standard security architecture used on Unix, Linux and Mac OS X systems. JPAM permits the use of PAM authentication services to Java applications running on those platforms.

PAM was created in 1996 by Sun Microsystems. For more on PAM see the following resources:
PAM is available on all Unix systems, from Solaris to Linux to Mac OS X.

Jpam provides the integration with PAM.  Any Java application that needs to do authentication can potentially use jpam.

Commonly Java application authenticate using one of the following approaches and APIs:
However, there are many more approaches than these two. There are hundreds of authentication systems accessible through PAM. See a list for Linux here. Many of these are installed by default in the Linux distributions. Fedora Core 3 has 54 PAM modules in its /lib/security directory ready for use. Some notable examples of PAM modules are:

Name
Module
Use
SecurId
pam_securid.so
Authenticates SecurId hardware tokens with the RSAACE Server. Available from RSA as a free download. These have been tested with JPAM
Unix
pam_unix_*.so Authenticates using configured Unix scheme. This can be shadow passwords or NIS, depending on how the machine was configured. Tested with JPAM.
RADIUS
pam_radius.so Authenticates using RADIUS servers. Tested with JPAM.
CryptoCard
pam_smxs.so
Authenticates using CryptoCard RB1 hardware tokens and similar
Samba
pam_winbind.so
Authenticates using Windows and Samba servers.
Kerberos
pam_krb5.so
Authenticates with Kerberos/Active Directory
LDAP
pam_ldap.so
Authenticates with LDAP servers (from Java you could also use the JNDI API)
SafeWord
pam_safeword.so
Authenticates SafeWord tokens
DigiPass
pam_radius.so
DigiPass uses the Free Radius PAM module to authenticate DigiPass hardware tokens. DigiPass is from Vasco. These have been tested with JPAM.

Requirements

Jpam supports:

Dependencies

Apache Commons Logging is required for logging. This tool supports all of the common logging frameworks.

Operating Systems & Architectures

Operating Systems

JPAM supports:
  1. RedHat 9
  2. Fedora Core 1, 2 and 3
  3. Generic Linux
  4. Mac OS X
In addition, JPAM can be easily ported to any Unix-like operating system.

Windows does not use the PAM security concept hence Jpam is not applicable to Windows.

Architectures

Binary distributions are available for:
  1. i386
  2. amd64
  3. ppc (Mac OS X)
A source distribution is available which with the addition of an Ant property file for an architecture will build for that distribution. JPAM is portable to any architecture for which both Java and PAM are available.

JavaDoc

JavaDoc is distributed with all binary and source distributions.

It is also available online here.


Configuration
The distribution contains an example pam.d configuration file called net-sf-jpam. To configure jpam, edit net-sf-jpam and copy it to /etc/pam.d. Follow the instructions in that file for the PAM module you configure. See http://jpam.sourceforge.net/documentation/#configuration for more information.

Limitations

Currently JPAM provides basic authentication services such as:
  1. Does the user exist?
  2. Are they allowed to log in?
  3. Are their credentials correct? 
Jpam does not support advanced PAM conversations such as:
However with the features already supported, JPAM is ready for many Java applications.

JAAS

Jpam comes with a JAAS implementation.

JAAS stands for  Java Authentication And Authorization Service. It is a Java analogue to PAM. PAM was also invented by Sun Microsystems. JAAS comes with some sample binary authentication modules. It has been left to vendors to provide specific implementations. JPAM fills a gap in the market by making the 70 plus PAM modules already available on Linux accessible to JAAS.

JPAM's implementation of JAAS's LoginModule is JpamLoginModule.

JPAM may also be used directly, circumventing JAAS, via its PAM class.

Configuring JAAS

JAAS uses login configuration files.

The JRE's java.security file specifies the default login configuration file as follows:

# Default login configuration file#
login.config.url.1=file:${user.home}/.java.login.config

To use JpamLoginModule with this defaul setting copy the supplied .java.login.config file to your home directory.

Its contents are reproduced below:


net-sf-jpam {
   net.sf.jpam.jaas.JpamLoginModule required;
 };

Sample Code

JPAM includes a number of tests to verify that the JpamLoginModule is functioning correctly. See the full test here.

The sample shown below shows how to:

  1. Create a new JAAS LoginContext and login.
  2. How to implement the required CallBackHandler for communication with the JpamLoginModule.

    /**
     * Checks that we can login.
     * <p/>
     * In this test, login is successful and commit is called.
     * @throws LoginException
     */
    public void testLoginContext() throws LoginException {
        LoginContext loginContext;
        loginContext = new LoginContext("net-sf-jpam", new JpamCallbackHandler());
        loginContext.login();
    }

    /**
     * The application must implement the CallbackHandler.
     * <p/>
     * <p> This application is text-based.  Therefore it displays information
     * to the user using the OutputStreams System.out and System.err,
     * and gathers input from the user using the InputStream, System.in.
     */
    class JpamCallbackHandler implements CallbackHandler {

        /**
         * Invoke an array of Callbacks.
         * <p/>
         * <p/>
         *
         * @param callbacks an array of <code>Callback</code> objects which contain
         *                  the information requested by an underlying security
         *                  service to be retrieved or displayed.
         * @throws java.io.IOException          if an input or output error occurs. <p>
         * @throws UnsupportedCallbackException if the implementation of this
         *                                      method does not support one or more of the Callbacks
         *                                      specified in the <code>callbacks</code> parameter.
         */
        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:
                            System.out.println(toc.getMessage());
                            break;
                        case TextOutputCallback.ERROR:
                            System.out.println("ERROR: " + toc.getMessage());
                            break;
                        case TextOutputCallback.WARNING:
                            System.out.println("WARNING: " + toc.getMessage());
                            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(user1Name);

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

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

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

    }

Extending JPAM

There are two main ways JPAM can be extended:
  1. Porting to new architectures
  2. Adding in PAM modules

Porting to New Architectures

JPAM uses native C code to communicate with PAM. The C code is compiled into a shared library. These are architecture dependent. To port to a new architecture:

  1. Add an ANT properties file for the architecture
  2. Add a new target to the src/c/makefile.
For most Unix-based systems that should be it.

Adding new PAM modules

Though not included in the binary distributions, SecurId and Radius have both been tested.


Debugging

JPAM consists of Java code, native code accessed through JNI and then PAM. When extending JPAM, it will be useful to turn on logging across all of these tiers.

Java and Native Code Logging

If the DEBUG logging level is enabled, jpam will show logging from Java. Because JPAM uses commons-logging, setting logging to DEBUG depends on your logging toolkit. For JDK1.4 logging, set your logging.properties to fine.

If DEBUG is set, libjpam.so will also log messages. As native code it does not use Java logging. It will log its messages to <stdout>.

PAM Logging

It is also useful to get PAM to log what it is doing.

To enable syslogd for PAM logging, add "auth.notice" to the /var/log/messages line in /etc/syslog.conf. e.g.

*.info;mail.none;authpriv.none;cron.none;auth.notice                        /var/log/messages



 SourceForge.net