The intended audience for this book is developers who use JPam. It should be able to be used to start from scratch, get up and running quickly, and also be useful for the more complex options.
JPam is a missing piece in the Java - Unix security puzzle. Another natural audience is therefore security specialists.
It is also intended for application and enterprise architects. JPam creates new possibilities. It is not necessary to front Java Application servers with Apache in order to plug in native security. You are no longer limited by the availability of Java implementations of security services.
This content is suitable for use as an online PDF or printed. Blank pages have been deliberately left to give a good flow.
JPam has had contributions in the form of forum discussions, feature requests, bug reports, patches and code commits.
Rather than try and list the many hundreds of people who have contributed to JPam in some way it is better to link to the web site where contributions are acknowledged in the following ways:
JPam is a Java-PAM bridge. PAM, or Pluggable Authentication Modules, is a standard security architecture used on Linux, Solaris, Mac OS X and other Unix systems. JPam is the missing link between the two.
JPAM permits the use of PAM authentication facilities by Java applications running on those platforms. These facilities include:
JPam supports 1.4, 1.5 and 1.6 at runtime. JPam final releases are compiled with -target 1.4. This produces Java class data, version 48.0.
JPam does not work with JDK1.2 or JDK1.1. JAAS is not available for these JDKs. Moreover, JNI used a different interface prior to JDK1.2.
IBM 1.4.2.0 JVM is known to work although it places its native libraries in a different place. Add -Dnative.java.library.path=/usr/lib/jvm/java-ibm/jre/bin (or wherever the IBM JVM is installed ) to your Java command line.
JPam requires commons-logging commons-logging is a very common dependency, and is therefore not included in the distribution.
Jpam also requires JAAS. Originally introduced as an optional package (JAAS 1.0) to version 1.3 of the Java 2 SDK, JAAS has now been integrated into the Java 2 SDK, version 1.4.
It has been reported that JPam relies on the presence of pam-devel-0.77-66.2 or similar RPMs.
JPam releases are placed in the central Maven repository.
The Maven snippet for JPam 1.0 is:
<dependency> <groupId>net.sf.jpam</groupId> <artifactId>jpam</artifactId> <version>1.0</version> </dependency>
JPam will create builds for the following:
PAM is used on Unix and Unix-like operating systems. JPam should be readily portable to other *nixes.
The steps are:
OS and Architecture | Native Library File | Java Native Library Path |
Linux AMD64 server | libjpam.so | $JAVA_HOME/lib/amd64/server |
Linux i386 client | libjpam.so | $JAVA_HOME/lib/i386/client |
Linux i386 server | libjpam.so | $JAVA_HOME/lib/i386/server |
Linux x86 client | libjpam.so | $JAVA_HOME/lib/i386/client |
Linux x86 server | libjpam.so | $JAVA_HOME/lib/i386/server |
Mac OS X PPC | libjpam.jnilib | ~/Library/Java/Extensions |
Solaris sparc | libjpam.so | $JAVA_HOME/lib/sparc/client |
Solaris sparc | libjpam.so | $JAVA_HOME/lib/sparc/server |
Native Library Installation Location
Alternately, JPam will search for the native library in the same directory as the JPam jar is located.
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.
PAM configuration files have four columns:
Possible values are:
The control flag is how the result of the operation is to be interpreted. Possible values are:
The path to the module
This column is optional. It is for any options to be passed to the module.
An example which uses the standard Unix password PAM module is shown below.
####################################################################### # Unix PAM Module # =============== # # If using pam_unix you may need to change /etc/shadow to be readable by # the user executing Jpam. ####################################################################### auth required /lib/security/pam_unix_auth.so account required /lib/security/pam_unix_acct.so password required /lib/security/pam_unix_passwd.so session required /lib/security/pam_unix_session.so
64 bit Linux distributions such as RedHat, Fedora, Suse and Novell Linux Desktop have adopted a convention of placing their 64 libraries in /lib64. The net-sf-jpam configuration file for these would look like:
####################################################################### # Unix PAM Module # =============== # # If using pam_unix you may need to change /etc/shadow to be readable by # the user executing Jpam. ####################################################################### auth required /lib64/security/pam_unix_auth.so account required /lib64/security/pam_unix_acct.so password required /lib64/security/pam_unix_passwd.so session required /lib64/security/pam_unix_session.so
However, there are many more approaches than these two. There are hundreds of authentication systems accessible through PAM. See a list fo Linux here. Many of these are installed by default in the Linux distributions. For example Fedora Core 3 has 55 PAM modules in its /lib/security directory by default.
Some notable examples of PAM modules are:
Name | Module | Use |
SecurId | pam_securid.so | Authenticates SecurId hardware tokens with the ACE Server. Available from RSA. |
Unix | pam_unix_+.so | Authenticates using the configured auth Unix scheme. e.g. shadow passwords or NIS. |
RADIUS | pam_radius.so | Authenticates using RADIUS servers. |
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. |
Popular Security Services
The path to the module shown above becomes the third column in the net-sf-jpam configuration line.
JPam will dynamically link to any Pam module which is installed on the operating system and specified in its configuration. No recompilation is required.
See http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html/pam.html for information on configuring PAM.
The JPam team believe that the first and most important quality measure is a well designed and comprehensive test suite.
JPam has a relatively high test coverage of source code. This has edged higher over time.
The JPam JUnit test suite contains some long-running system tests which place high load on different JPam subsystems to the point of failure and then are back off to just below that point. The same is done with limits such as the amount of Elements that can fit in a given heap size. The same is also done with performance testing of each subsystem and the whole together. The same is also done with network tests for cache replication.
The tests serve a number of purposes:
JPam also has concurrency testing, which uses 15 concurrent threads hammering a piece of code. The test suites are also run on multi-core or multi-cpu machines so that concurrency is real rather than simulated. Additionally, every concurrency related issue that has ever been anticipated or resulted in a bug report has a unit test which prevents the condition from recurring. There are no reported issues that have not been reproduced in a unit test.
Concurrency unit tests are somewhat difficult to write, and are often overlooked. The team considers these tests a major factor in JPam's quality.
JPam has been in production for 18 months.
A core belief held by the project team is that a project needs good documentation to be useful.
In JPam, this is manifested by:
Projects like Linux maintain their quality through a restricted change process, whereby changes are submitted as patches, then reviewed by the maintainer and included, or modified. JPam follows the same process.
Through the SourceForge project bug tracker, the full history of all bugs are shown, including current status. We take this for granted in an open source project, as this is typically a feature that all open source projects have, but this transparency makes it possible to gauge the quality and riskiness of a library, something not usually possible in commercial products.
The JPam team is serious about quality. If one user is having a problem, it probably means others are too, or will have. The JPam team use JPam themselves in production. Every effort will be made to provide fixes for serious production problems as soon as possible. These will be committed to trunk. From there an affected user can apply the fix to their own branch.
JPam's original Apache1.1 copyright and licensing was reviewed and approved by the Apache Software Foundation, making JPam suitable for use in Apache projects. JPam 1.0 is released under the updated Apache 2.0 license.
The Apache license is also friendly one, making it safe and easy to include JPam in other open source projects or commercial products.
Pam Class Diagram
Attempt to authenticate a username and password
String user1Name = "test"; String user1Credentials = "testPassword"; Pam pam = new Pam(); boolean authenticated = pam.authenticateSuccessful(user1Name, user1Credentials));
JPamLoginModule Class Diagram
Shows how to use the JAAS API together with a CallbackHandler.
LoginContext loginContext = new LoginContext("net-sf-jpam", new JpamCallbackHandler()); loginContext.login(); 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"); } } } }
JPam comes with a comprehensive JUnit test suite, which not only tests the code, but shows you how to use JPam.
A link to browsable unit test source code for the major JPam classes is given per section. The unit tests are also in the src.zip in the JPam tarball.
JPam uses the Apache Commons Logging library for logging.
It acts as a thin bridge between logging statements in the code and logging infrastructure detected in the classpath. It will use in order of preference:
This enables JPam to use logging infrastructures.
It does create a dependency on Apache Commons Logging, however many projects share the same dependency.
For normal production use, use the WARN level in log4J and the WARNING level for JDK1.4 logging.
If the DEBUG logging level is enabled, JPam will instruct libjpam.so to log messages to the console. This is very useful for identifying errors.
It can be useful to turn on syslogd for PAM logging. Library problems with PAM modules will then be logged.
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
Then simply tail /var/log/messages to see PAM logging.
No, it is not supported.
It is easy to make the changes to the build.xml and makefile to support other architectures. Do it and submit a patch! Both Solaris and HP-UX support come from patches.
Jpam presently does not support advanced PAM conversations such as:
These may be added into a future version.
To build JPam from source:
The source download and the CVS source contain a src/rpm directory containg an RPM spec file created in collaboration with developers at Red Hat. You can use this spec.file to build an rpm installable package for your architecture.
(These instructions are for project maintainers)
You need the following unix utilities installed:
You also need a yDoc license.
With all that, build the site as below:
mvn site:site
Logo
The JPam logo has a blue rectangle representing a Unix OS (blue is the Solaris colour), Java (the purple colour) and PAM (the small rectangles), which is what JPam is all about.