| By Michael Remijan | Article Rating: |
|
| October 3, 2007 11:45 AM EDT | Reads: |
30,454 |
Tomcat is a great reference implementation of the Java EE specification and is intended for desktop use by developers who are starting to learn about Java EE or those who work on enterprise applications and need an EE server for development. However because Tomcat is free it finds its way into production environments. In this environment there are features of Tomcat that don't pass security audit reviews. One of these features is the use of clear text passwords in the server.xml file to create data sources. The purpose of this article is to show how encryption of the username and password can be implemented thus closing a potential security vulnerability.
Configuring a container managed data source with Tomcat is easy and well documented under the "JDBC DataSources" section of Tomcat's documentation (this article uses Tomcat 5.0.28). The data source configuration information is stored in TOMCAT/conf/server.xml. The resource is defined using the <Resource/> tag.
<Resource
name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
/>
The name attribute defines where the resource is bound in JNDI. The auth attribute will have either the value Application or Container. Container means Tomcat will provide the username and password to connect to the resource whereas Application means the application will provide them. Container is specified because the username and password will be entered in server.xml. The type attribute is the fully qualified name of the class returned when the resource is looked up using JNDI.
Next the resource needs to be configured. This is the purpose of the <ResourceParams/> tag. For a JDBC resource, a basic configuration is presented in Listing 1.
The name attribute has the value jdbc/TestDB, which must match a <Resource/> tag. The "factory" name/value pair tells Tomcat the fully qualified name of the class that implements javax.naming.spi.ObjectFactory. This class is responsible for returning objects of the type defined by the type attribute of the <Resource/> tag. The rest of the name/value pairs of <parameter/> tags are passed to the "factory" in a javax.naming.Reference object.
Finally, the application has to be configured to use this data source. This is done by referencing the data source in /META-INF/context.xml of the application's WAR. A <ResourceLink/> tag is added to context.xml.
<ResourceLink
global="jdbc/TestDB"
name="jdbc/SpiderMan"
type="javax.sql.DataSource"
/>
The type attribute is the fully qualified name of the class returned when the resource is looked up using JNDI. The global attribute must match a <Resource/> tag in server.xml. The name attribute defines where the resource is bound in JNDI. From an application's point of view, the location specified by the name attribute is relative to java:comp/env. Each application can have its own conventions for JNDI lookup names and the <ResourceLink/> tag is the bridge between how an application does a resource lookup and where the resource is actually located. It's good practice to have the application use an atypical lookup name. This makes your application more portable to other EE servers because it's not accidentally bound to the conventions of one EE server's resource placement.
For development environments or personal use this configuration is acceptable, however, in a production environment the clear text username and password in <ResourceParams/> is a security vulnerability. If a production server is compromised, the intruder would have easy access to production data. With privacy concerns and Sarbanes-Oxley requirements the harder it is for an intruder to gain access to such data the better.
While Yahooing! I was surprised to discover I couldn't find any instructions addressing this issue. Most search results related to debating if securing the clear text username and password is even necessary. The general consensus seemed to be this security is not necessary for two reasons. One, if an intruder compromises a production server in a way that would allow read access to server.xml then the clear text username and password is the least security concern. Two, Tomcat is a reference implementation so it shouldn't be used in a production environment. Although these are lively debates and can spark great topics of conversation they do not address the issue. What I need is a way to get rid of the clear text username and password.
I will present three possible solutions to this issue. The first two are custom solutions involving application updates while the third takes advantage of Tomcat's built-in extensibility, requires no application updates and so is a much more attractive solution.
The first solution is to bypass Tomcat altogether and not configure a data source. With no data source there's no clear text username and password in server.xml so the problem is solved. However applications still need database connections. With no container-managed database pool each application will have to do its own pooling. This brings up all sorts of problems. Applications will need knowledge of the database and how to access it, unnecessary plumbing code is needed to manage the pool, data access objects will no longer be coded to EE specs making them less portable, no built-in or plug-in transaction management resulting in more plumbing code, an ever-growing number of connections as more applications are developed, performance degradation during high-traffic periods as connections become scarce, support overhead from managing many individual configurations, and the list goes on. It's possible each of these problems can be solved but as you solve them your code moves further and further from the EE specs. Because of all these problems, this is not an attractive solution.
The second solution is to move the responsibility for database authentication from Tomcat to the application. Recall the auth attribute of the <Resource/> tag. If the value is Application, the application is responsible for providing the username and password. The Tomcat administrator can delete the username and password parameters from server.xml and the Developer would code the username and password into the application. Typically the first time JNDI is used to look up a DataSource is when the username and password are set. The code in Listing 2 gives an idea of what this would look like for Tomcat. Although the example doesn't use any kind of encryption it's not difficult to plug in an encryption strategy. This solution also has problems. The application is now responsible for either knowing the username and password or knowing the encryption strategy. The application also needs to know the real class implementing DataSource (in the case of Commons DBCP) so the username and password can be provided. This could make the application not portable to another EE server. So this is not an attractive solution either.
The third solution is to take advantage of Tomcat's built-in extensibility. Inside the <ResourceParams/> tag Tomcat offers the ability to specify the fully qualified name of the Java class that implements the javax.naming.spi.ObjectFactory interface. This class is responsible for returning implementations of javax.sql.DataSource. By default Tomcat uses org.apache.commons.dbcp.BasicDataSourceFactory and this class requires <ResourceParams/> to have clear text username and password values. So why not create a class that extends BasicDataSourceFactory and is configured with an encrypted password instead? For the purposes of this article I'll use a simple Base64 encoding but the concept can be easily extended to any other method.
The source code for BasicDataSourceFactory has two important methods. They are:
public Object
getObjectInstance(
Object o
, Name n
, Context c
, Hashtable h)
public static DataSource
createDataSource(
Properties p
)
Published October 3, 2007 Reads 30,454
Copyright © 2007 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
About Michael Remijan
Michael J. Remijan is a research programmer at the National Center for Supercomputing Applicaitons (NCSA). His chief responsibilities include data miming and access to terabyte-sized astronomy data sets. Michael received a BS in mathematics and computer science from the University of Illinois and is currently working on an MBA in technology management.
![]() |
sn72 11/09/08 09:26:48 PM EST | |||
A similar solution is to create a MySQL driver. That is, create a class derived from com.mysql.jdbc.NonRegisteringDriver. Create a static initializer block to register the class with java.sql.DriverManager, following the example in com.mysql.jdbc.Driver. Override the following functions: public Connection connect(String string, Properties properties) throws SQLException public boolean acceptsURL(String string) throws SQLException In the connect function lookup the username and pasword in the properties using 'user' and 'password'. Decrypt the password (maybe there can be a different algorithm for each user). Install the decrypted password back into 'properties'. One advantage of this solution is that you can use the custom driver with standalone JUnit tests and swing code. |
||||
![]() |
Chris 04/19/08 10:49:36 AM EDT | |||
Hi Michael, thanks a lot. That was the stuff we needed. You saved me a lot of hours having headache about this stuff. May be you will submit your code to apache. I missed this functionality baddly in commons-dbcp. Once again thanks a lot. Chris |
||||
![]() |
Fret 10/05/07 12:15:08 PM EDT | |||
Would this work in Glassfish also? |
||||
![]() |
Pavel Buzek 10/04/07 02:00:57 PM EDT | |||
Just a technical correction: the article says "Tomcat is a great reference implementation of the Java EE specification" ... well, of course it isn't. Tomcat is not even an implementation of Java EE spec (only a small subset of it) so it cannot be the reference impl, which is [https://glassfish.dev.java.net/]. |
||||
![]() |
Wayne 10/03/07 10:28:24 AM EDT | |||
Michael, This posting was exactly what I needed. Thank you Thank you Thank you !!! |
||||
![]() |
Rob 09/11/07 04:44:26 PM EDT | |||
The third solution is very interesting, but a bit vague on a key detail. How are you proposing you encrypt this data? Are you storing the encryption key were the tomcat server has access to it in clear text? As long as that is so there is still no secret, just an extra hurdle. |
||||
![]() |
Suilong 08/28/07 10:35:09 AM EDT | |||
very helpful article. thank you |
||||
![]() |
Madhu 08/02/07 10:20:07 AM EDT | |||
Hi Michael, Your article is great and helped me since it was exactly what I needed. The documentation for implementation in supplemental download requires the use of org.moss.jdj.dbcp-yyyy.mm.dd.jar. It provides a link to the location of that jar in the download, but the jar is not there. Is there some other location I can download the jar from? Thank you. |
||||
![]() |
Rafael 07/31/07 11:01:13 AM EDT | |||
Michael, may I use the third example you provided the same way when specifying my connection parameters in an xml file located at Regards |
||||
![]() |
ebuild 07/31/07 10:41:51 AM EDT | |||
You said : |
||||
- Performance of Java Compilers: An Empirical Study
- Java Kicks Ruby on Rails in the Butt
- Ulitzer’s Amazing First 30 Days in Public Beta
- 1st Annual Government IT Expo: Call for Papers Deadline July 15
- REA Is Where RIA Becomes the Norm
- Why an Application Grid?
- Will Ulitzer Dominate News Content on The Web? -Gartner
- Clear Toolkit 4: The Road Map
- Profiling Netbeans within Amazon EC2
- Java Persistence on the Grid: Approaches to Integration
- Performance of Java Compilers: An Empirical Study
- Java Kicks Ruby on Rails in the Butt
- Developing Rich Client Applications Using Swing - II
- The Right Time for Real Time Java
- Xpress Suite Adds Automatic Java to iPhone Conversion
- Ulitzer’s Amazing First 30 Days in Public Beta
- Initial Thoughts on IBM Acquisition of Sun Microsystems
- 1st Annual Government IT Expo: Call for Papers Deadline July 15
- Maximizing Java Performance with Bespoke Programming
- REA Is Where RIA Becomes the Norm
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- The i-Technology Right Stuff
- JavaServer Faces (JSF) vs Struts
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- What's New in Eclipse?
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate








































