Sunday, January 28, 2007

Java: Intro to LDAP

I am just coming off of an assignment where part of the task was to implement an authentication routine against a LDAP repository. Having never worked with LDAP before, I downloaded IBM’s Tivoli Directory Server and followed the instructions here to getting it set up and getting a basic directory. The version I used was 5.1. While doing the install, I did end up having a problem with DB2 when I got to the point of configuring the database for LDAP. To correct this I had to re-install DB2 from the installation disk seperatly and install a fix level (sorry for the lack of instructions on that, I’m writing this after the fact, so I don’t have the specifics).

Anyway, below is my resulting test program. While different LDAP repositories can follow different schemas (such as the one I had to work with in real time used different attribute names), this one will work for the one in the IBM tutorial listed above. Working with LDAP can be tricky if you’ve never worked with it before due to the confusion of using full DN’s vs when you can use RDN’s. Basically, LDAP is just a repository for named user objects. In the IBM example, you have a user, with particular attributes, and each user is stored in the people tree of the repository. What gets confusing is the use of DN’s. DN’s are the names. To access things, you reference a full DN to search for one that has a particular attribute that matches. You can pretty much always use DN’s anywhere, and writing a small utility method that will append the full DN to a RDN can be helpful.

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import java.util.Hashtable;
import java.util.ArrayList;

public class javaLdapTEst {

public static void main(String[] args) {
Hashtable contextSetup = new Hashtable(); //contains the configuration for the context setup
String uidToSearch = "(uid=c0001)"; //The user ID we are searching for
String baseDN = "dc=ibm, dc=com"; //The base DN for the entire LDAP structure
String baseUserDN = "ou=people, " + baseDN; //the base DN to use to search for people. This will
//contain the full DN for the users tree. Role trees
//are usually contained in a seperate node, which is
//outside of the scope of this example

//create the parameters to use during initialization of the LDAP context
contextSetup.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
contextSetup.put(Context.PROVIDER_URL, "ldap://192.168.254.128:389");
contextSetup.put(Context.SECURITY_CREDENTIALS, "ibm4root");
contextSetup.put(Context.SECURITY_PRINCIPAL , "cn=root,");
contextSetup.put(Context.URL_PKG_PREFIXES, "com.sun.jndi.url");

try {
//Create the context used to communicate with the LDAP server throughout
DirContext dContext = new InitialDirContext(contextSetup);

//SEtup the search object. With this, we will pass in a base DN, and search all the child nodes
//In the ldap
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

//Execute the search, and display all the resulting attributes, and display all matches
for (NamingEnumeration results = dContext.search(baseUserDN, uidToSearch, searchControls); results.hasMore();)
{
//Get the next individual result
SearchResult result = (SearchResult)results.next();

//Print out the name
System.out.println(result.getName());

//Display all resulting attributes
for (NamingEnumeration attributes = result.getAttributes().getAll(); attributes.hasMore();)
{
String attribute = attributes.next().toString();
System.out.println(attribute);
}

//Display the email addresses that this user has
for (NamingEnumeration mail = result.getAttributes().get("mail").getAll(); mail.hasMore();)
{
System.out.println("Email addresses: " + mail.next().toString());
}

System.out.println("---------------------------------\n\n");

}
} catch (NamingException e) {
e.printStackTrace();
}
}

}

Thursday, January 25, 2007

Travel: Memorex iFlip Portable Video Screen for IPod Video

Since I am traveling quite a bit, I picked up a Memorex Mi8000BLK iFlip for my Ipod Video. I can't stand the small screen, so I figured a nice portable video unit was the solution.

The Pros:
Screen is big
Sounds good
SVideo and RCA Audio output looks decent (artifacting was not fault of unit, but off video compression, but it was more than watchable).
Durable

The Cons:
Big and Bulky
OnScreen pixels are very noticable, and its an LCD???
Screen colors seems a little washed out
Opening is a little difficult


Overall, I am pleased with the device. I don't have to get a portable DVD player since I can easily grab my DVD's using CuCusoft DVD to Ipod and store them on my IPod for inflight entertainment, or purchase stuff off ITunes (I just picked up the first season of Lost, something I missed on TV so I figured I would catch up).

The one thing I will say is that this is a toy. If you don't need one, don't buy it. It makes travel a little more tolerable. I do have to say, it is kind of cool to pull this thing on on a flight and have the passengers around me peek over to look as well.

Travel: Quick, Convienent Motorola Razr Phone Charger Using your Laptop

I'm on the road for the next few weeks, with no time at home. When traveling, I like to travel light, and by light I mean I don't want a whole lot off items I need to keep track of which have the potential to be forgotten. This includes my phone charger, which as anyone with a cell phone knows is the lifeblood and usually an often forgotten item during travels. I have a Motorola V3C Razr, which I've had for some time now. Since I travel on business, I also have my laptop. After I first got my laptop, I came across this driver which allows me to charge my phone from my laptop. It does not let me use it as a modem or for broadband, which is a feature that Verizon offers for my phone, but I am not willing to pay 50 dollars a month. So now I don't have to keep track off my phone charger, I can just keep a inexpensive, run off the mill, USB cable with me and plug my phone in while I am working.

This brought up a little musing in my mind about how portable the office really has gotten. Lets review. This time last year I was sitting in an office with a desktop computer, my desk phone, and my 60 gig MP3 server. Now, I have my laptop, which my cell phone plugs into and I can use without fear of running the batter down, my 60 gig IPod video plugged in charging and playingg music for me and storing movies for me to watch while I travel.

While all this technology as been around for years, and road warriors have been doing this for longer than I have, I am amazed how much a year can change things, and how convienent this portable technology is. It has enabled me to have all the comforts of my static office when out on the road.

Wednesday, January 10, 2007

Java: Read and Write Encrypted Data to a Database

I am taking another break from my RCP application to focus on an issue that was asked in one of the BIRT newsgroups. The basic question was, how can a user retrieve an encrypted value from a database, decrypt it, and display in a report. While many database packages provide encryption packages, I prefer to use client side decryption routines so that decrypted values are not transmitted over the wire. First part of this is to get an encrypted value into the database using Oracle JDBC driver by using prepared statements, and retrieve those values and decrypt. The following example will do just that. I am using a TripleDES class as demonstrated in David Flanagans Java Examples in a Nutshell. The below example will simply read a key from an already generated key located at C:\Eclipse\Workspace\TripleDES, encrypt the string “This is a test String”, insert into a database, read from a database, decrypt and output to the console. I have also already added the Oracle JDBC driver to my classpath.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

public class WriteValueToDatabase
{
public static void main(final String[] args)
{
try
{
//variable declarations, file where the key is located, and the input and output streams
final File f = new File("/eclipse/workspace/TripleDES/myKeyFile.txt");
final ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream("This is a test String".getBytes());

//handle the database settings
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();

//Instantiate the OracleDriver
final Connection con = DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.110:1521:birt", "digiassn", "r00s7er");
//Statement for reading from the database
final Statement stmt = con.createStatement();
//Prepared statement for writing to the database. We need this since the field is a raw field
final PreparedStatement pset = con.prepareStatement("insert into encryptTest (encrypted) values (?)");

//Read the secret key from the file and encrypt the string created as a stream above
final SecretKey key = TripleDES.readKey(f);
TripleDES.encrypt(key, in, out);

//Here, insert the encrypted value into the database
pset.setBytes(1, out.toByteArray());
pset.executeUpdate();

//Now, read the result back from the database
final ResultSet set = stmt.executeQuery("select * from encryptTest");

//Cycle through the resultset
while (set.next())
{
//REuse my input stream by casting the stream read from the resultset
in = (ByteArrayInputStream) set.getBinaryStream(1);

//Output the value read from the database
System.out.print("Value read from database: ");
TripleDES.decrypt(key, in, System.out);
System.out.println();
}

pset.close();
set.close();
stmt.close();
con.close();
//Auto generated catch from Eclipse
} catch (final InvalidKeyException e)
{
e.printStackTrace();
} catch (final NoSuchAlgorithmException e)
{
e.printStackTrace();
} catch (final InvalidKeySpecException e)
{
e.printStackTrace();
} catch (final NoSuchPaddingException e)
{
e.printStackTrace();
} catch (final InstantiationException e)
{
e.printStackTrace();
} catch (final IllegalAccessException e)
{
e.printStackTrace();
} catch (final ClassNotFoundException e)
{
e.printStackTrace();
} catch (final SQLException e)
{
e.printStackTrace();
} catch (final IOException e)
{
e.printStackTrace();
} catch (final BadPaddingException e)
{
e.printStackTrace();
} catch (final IllegalBlockSizeException e)
{
e.printStackTrace();
}
}

}

Friday, January 05, 2007

Tomcat: Publishing My Web Service from Eclipse to Tomcat

So, now I have created a basic web service in Eclipse. I want to publish it to an Apache Tomcat server permanently, not just for testing using Eclipses Server debug mode. Fortunately, Eclipse makes this easy to export, and Tomcat makes this easy to import.

First step is to select the project in the Eclipse Project Explorer. Right-Mouse clicks on the project and choose Export. Under the export menu, choose Web/WAR File. By default, your class should appear under the Web Module, or under the drop down list. If it doesn’t, something went wrong. Choose a Destination directory (in my case, I choose C:\TEMP) and your all set.

Now, go to your Tomcat Manager URL. In my case, it is http://localhost:8080/manager/html.

Once there, I go down the about 2/3 of the page in the Upload a War file to Install section, choose Browse, go to the C:\Temp folder, and select my .WAR file. Then I select the Install button. Now, I can see the MyWebService under the list of applications. Now comes the tricky part. If I click on it, I will get a 404 Page Not Found error. The reason being, the context is set differently in the web apps web.xml file.

To find out the correct location, I go to see the WSDL file that got imported under my Tomcat webapps folder. For me, this is located at C:\Program Files\Apache Software Foundation\Tomcat 4.1\webapps\MyWebService\wsdl\MyWebService.wsdl. Once I open up this file, I get clued into the location to find my web service, which is at http://localhost:8080/MyWebService/services/MyWebService. To confirm this works, I pull the online WSDL file at http://localhost:8080/MyWebService/services/MyWebService?wsdl.

Now I am ready to move on with my RCP application since the planned exodus of Googles Web Toolkit.