Difference between revisions of "ATNA FAQ"

From IHE Wiki
Jump to navigation Jump to search
 
Line 358: Line 358:
 
===How do I Log a message when someone fails to connect to Tomcat?===
 
===How do I Log a message when someone fails to connect to Tomcat?===
 
Normally, when a TLS Connection fails to attach, Tomcat ignores it and goes on its merry way.  However, under ATNA, it should send a message to the appropriate SysLog daemon.  So you have to take control of the SSL Implementation that is used for your connector.  To do this, add the line in bold to your connector.
 
Normally, when a TLS Connection fails to attach, Tomcat ignores it and goes on its merry way.  However, under ATNA, it should send a message to the appropriate SysLog daemon.  So you have to take control of the SSL Implementation that is used for your connector.  To do this, add the line in bold to your connector.
<pre>
+
 
 
     <Connector port="8443" acceptCount="100"  
 
     <Connector port="8443" acceptCount="100"  
 
       disableUploadTimeout="true" enableLookups="true"  
 
       disableUploadTimeout="true" enableLookups="true"  
Line 371: Line 371:
 
       truststorePass="changeit"
 
       truststorePass="changeit"
 
       truststoreType="JKS"
 
       truststoreType="JKS"
       SLImplementation="net.ihe.iti.atna.net.tomcat.ATNAImplementation"
+
       <b>SLImplementation="net.ihe.iti.atna.net.tomcat.ATNAImplementation"</b>
 
     />
 
     />
</pre>
+
 
 
Now, compile the following Java code and install the class files into C:\tomcat\server\classes\net\ihe\iti\atna\net\tomcat (that's assuming you've installed Tomcat at C:\tomcat).  Oh, BTW, you need to put C:\tomcat\server\lib\tomcat-util.jar in your classpath when you compile.
 
Now, compile the following Java code and install the class files into C:\tomcat\server\classes\net\ihe\iti\atna\net\tomcat (that's assuming you've installed Tomcat at C:\tomcat).  Oh, BTW, you need to put C:\tomcat\server\lib\tomcat-util.jar in your classpath when you compile.
 
<pre>
 
<pre>

Revision as of 10:28, 22 November 2006

The purpose of this FAQ is to describe the various steps I have taken to make Tomcat 5.X support TLS communications on Windows 2000 and Windows XP with Java Applications. Some of this information will also be of interest to Unix users, and may be of interest to C# and .NET programmers as well, as the same basic principles apply.

NOTE: This FAQ was last updated for the 2005-2006 Connectathon.

What is TLS?

The IHE ATNA and XDS Integration profiles require the use of the Transport Layer Security Protocol, or TLS. TLS was originally defined by RFC-2246 and updated by RFC-3546.

TLS is essentially the SSL protocol with certificates exchanged on both sides, instead of just one side when communicating to web servers to do any HTTP interactions. If you really didn't know any of this, you should seriously ask yourself why you are doing this and not someone else.

What Tools Do I Need?

Three tools are absolutely critical, A protocol Analyzer, Open SSL, and the J2SE Unlimited Cryptography policy files. The first will allow you to see what it happening when connecting to a server or client. The next, Open SSL, will let you see inside certificates. The J2SE policy files will enable support for the ATNA encryption option in the Java Virtual Machine. How can I see what is happening? The best way to see what is happening when you try to create a connection is to use a protocol analyzer. I use Ethereal, which has some support for parsing SSL and TLS packets. The next best way is to turn on the javax.net debugging features built into java. Just add the following line to your java command line, and you'll get loads of good stuff.

-Djavax.net.debug=ssl,handshake,data,trustmanager,help

How come I don't see any traffic in my protocol analyzer? Don't try to analyze traffic that never goes onto the wire, it won't work. If you are trying to analyze traffic from one system to itself, that traffic never hits the wire (it stays in memory), and so your protocol analyzer will never see it. You need at least two machines, one to act as a server, and one to act as a client. The protocol analyzer can run on either.

How can I create, or see what is in a certificate?

OpenSSL is a tool that will allow you to create and inspect certificates, and test servers and clients. A binary distribution for OpenSSL build for Windows 2000/XP is available from http://www.slproweb.com/products/Win32OpenSSL.html.

How do I support the ATNA Encryption Option?

In order to support encryption, you will need to install the Java Cryptographic Extension Unlimited Strength Jurisdiction Policy Files. For J2SE 1.4.2, these can be found at http://java.sun.com/j2se/1.4.2/download.html. For J2SE 1.5.0, these can be found at http://java.sun.com/j2se/1.5.0/download.html. Download these files, unzip them, and install them according to the instructions. This will enable use of TLS_RSA_WITH_AES_128_CBC_SHA (see ITI-TF 2:3.19.6.1).

Where is TLS_RSA_WITH_NULL_SHA

If you are using Sun's Java implementation, use SSL_RSA_WITH_NULL_SHA, which is the same thing. See http://forum.java.sun.com/thread.jspa?threadID=579499&messageID=3067960

What Do I Do with Certificates and Keys?

When using J2SE, the certificates and keys you have need to be put into special files called KeyStore or TrustStore files. The KeyStore file contains certificates that you have a private key for. This file should contain your system's private key and certificate. The trust store contains certificates that you trust, and should contain the certificates of any client that you will connect with (and any certificates in their chain).

The KeyStore file will be created in PKCS12 format (see How do I create the KeyStore?), so that you can insert your key and certificate into it. The TrustStore file should be created in JKS format, so that you can import multiple keys into it (see [How do I create the TrustStore?]). Take the resulting file (KeyStore, and put it in your Tomcat configuration folder (C:\tomcat\conf if Tomcat is installed at c:\Tomcat).

Why Do I need to use PKCS12 for my KeyStore, and JKS for my TrustStore?

The server certificate assigned to you has both a key and certificate. The Java keytool facility does not allow you to import a key into a KeyStore, it only allows you to generate a new key. OpenSSL will allow you to do this, but it cannot generate JKS format files, it can only generate PKCS12 files. On the other side, the TrustStore file can contain a list of certificates. However, OpenSSL will not create a PKCS12 file containing multiple certificates that the Java security tools can read (as far as I have been able to determine), so you need to use the Java keytool to import certificates into a TrustStore file.

What Format is My Certificate?

If your certificate was issued by Steve Moore, then it will be in PEM format. If it came from Bill Majurski, you can find it in either format. Look inside the file that you think is your certificate. If it contains ASCII text that starts with -----BEGIN CERTIFICATE-----, then it is in PEM format. If it is unreadable, then it's in PKCS12 format. If it reads instead: -----BEGIN RSA PRIVATE KEY-----, then what you have is a private key.

Why do/don't I need a Password to use my Key?

Your private key should normally be treated like a credit card number. Anyone with your private key can act like you, so it critical to securing your system. So, private keys are typically encrypted using triple-DES with a password. That is why you need a password to access the data in your private key. However, Steve Moore doesn't usually put a password on the private keys assigned to for testing, so these keys don't require one.

Why do I need a Password for my KeyStore and TrustStore files?

Your private key should be treated like a credit card number. Anyone with your private key can act like you, so it critical to securing your system. These are stored in the KeyStore file, and so this file is password protected. The TrustStore file lists the certificates for everyone your system trusts. You don't want anyone other than yourself from dinking with this list. So, this file is password protected as well.

How do I create the KeyStore?

Assuming you've installed OpenSSL and that it is in your path, change to the Mesa runtime certificates folder, and execute the following command (text in bold is what you enter):

C:\mesa\runtime\certificates>openssl pkcs12 -export -out KeyStore -in test_sys_1.cert.pem -inkey test_sys_1.key.pem
Loading 'screen' into random state - done
Enter Export Password: changeit
Verifying - Enter Export Password: changeit

Take the resulting file (KeyStore, and put it in your Tomcat configuration folder (C:\tomcat\conf if Tomcat is installed at c:\Tomcat).

How do I create the TrustStore?

Create the TrustStore file using the java keytool command. Assuming that you have installed Java 2 Standard Edition, and that java/bin is in your path, change to the Mesa runtime certificates folder, and execute the following command (text in bold is what you enter):

C:\mesa\runtime\certificates>keytool -import -alias mesa -file mesa.cert -keystore TrustStore
Enter keystore password: changeit
Owner: EMAILADDRESS=moores@mir.wustl.edu, CN=Steve Moore, OU=MIR, O=Washington University, L=St. Louis, ST=Missouri, C=US
Issuer: EMAILADDRESS=moores@mir.wustl.edu, CN=Steve Moore, OU=MIR, O=Washington University, L=St. Louis, ST=Missouri, C=US
Serial number: 0
Valid from: Wed Apr 24 13:28:06 EDT 2002 until: Thu Apr 24 13:28:06 EDT 2003
Certificate fingerprints:
         MD5:  2D:89:15:CA:23:16:A6:B5:3E:73:48:80:72:13:AC:99
         SHA1: 55:BB:65:F5:F7:74:7A:32:1E:BF:5B:E7:F8:A4:96:86:43:F7:C7:F9
Trust this certificate? [no]:  y
Certificate was added to keystore

Repeat the above command five more times, using a different alias for each key, for each of mesa_1.cert.pem through mesa_4.cert.pem, and for test_sys_1.cert.pem (you do trust yourself, don't you?) as shown below.

keytool -import -alias mesa1 -file mesa1.cert.pem -keystore TrustStore
keytool -import -alias mesa2 -file mesa2.cert.pem -keystore TrustStore
keytool -import -alias mesa3 -file mesa3.cert.pem -keystore TrustStore
keytool -import -alias mesa4 -file mesa4.cert.pem -keystore TrustStore
keytool -import -alias test_sys_1 -file test_sys_1.cert.pem -keystore TrustStore

Take the resulting file (TrustStore, and put it in your Tomcat configuration folder (C:\tomcat\conf if Tomcat is installed at c:\Tomcat).

How do I configure Tomcat?

If you are implementing an XDS Registry or XDS Repository Actor, you will need to configure the connector that your web application is running under to support TLS. The connector needs to know where your KeyStore and TrustStore files are located, what password to use to access them, and what format they are in. You will also need to tell it to support the TLS protocol, the SSL_RSA_WITH_NULL_SHA cipher, the TLS_RSA_WITH_AES_128_CBC_SHA cipher, and that it requires a client certificate. See "How do I configure Tomcat as an XDS Registry or XDS Repository?" for more details on how to set this up. If you are implementing an XDS Document Source or XDS Document Consumer, then you will need to configure the JVM to use your trust stores for https: connections. See "How Do I set up Tomcat as an XDS Document Source or Consumer?" for more details on how to set this up. How do I configure Tomcat as an XDS Registry or XDS Repository? Tomcat 5.X supports SSL and TLS encryption. Assuming you've installed Tomcat with documentation on your local server, you can read the documentation about it found at http://localhost:8080/tomcat-docs/ssl-howto.html or go here http://tomcat.apache.org/tomcat-5.5-doc/ssl-howto.html

Configure your server to support SSL by setting it up according to the instructions on that page.

Assuming you've created a KeyStore and TrustStore according to the directions above, you can set up Tomcat for TLS communications by adding the text in bold below to the server.xml found in the conf folder of your tomcat installation.

To support the encryption option, change SSL_RSA_WITH_NULL_SHA to TLS_RSA_WITH_AES_128_CBC_SHA in the ciphers attribute.

  <Service name="Catalina">
    <Connector acceptCount="100" connectionTimeout="20000" 
	disableUploadTimeout="true" port="8080" redirectPort="8443" 
	maxSpareThreads="75" maxThreads="150" minSpareThreads="25">
    </Connector>
    <Connector port="8443" acceptCount="100" 
      disableUploadTimeout="true" enableLookups="true" 
      scheme="https" secure="true" sslProtocol="TLS" clientauth="true" 
      keystoreFile="C:/tomcat/conf/KeyStore"
      keystorePass="changeit" 
      keystoreType="PKCS12"
	ciphers="SSL_RSA_WITH_NULL_SHA"
      maxProcessors="75" 
      maxThreads="75" 
      truststoreFile="C:/tomcat/conf/test_sys_1.cert"
      truststorePass="changeit"
	truststoreType="JKS"
    />
    <Engine defaultHost="localhost" name="Catalina">
      <Host appBase="webapps" name="localhost">
        <Logger className="org.apache.catalina.logger.FileLogger" 
		prefix="localhost_log." suffix=".txt" timestamp="true"/>
      </Host>
      <Logger className="org.apache.catalina.logger.FileLogger" 
		prefix="catalina_log." suffix=".txt" timestamp="true"/>
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"/>
    </Engine>
  </Service>

How Do I set up Tomcat as an XDS Document Source or Consumer?

To configure Tomcat for client operations, you need to update the registry settings used by the JVM when Tomcat starts. Open the registry key "HKEY_LOCAL_MACHINE\ SOFTWARE\Apache Software Foundation\Procrun 2.0\Tomcat5\Parameters\Java" using regedt32.exe. Edit the Options value, adding the options shown in bold below. Add the last option in bold italics if you want to get debugging output printed to stdout.log, but for production use, leave this off. You probably want to leave this on for connectathon testing with TLS.

-Dcatalina.home=C:\Tomcat
-Djava.endorsed.dirs=C:\Tomcat\common\endorsed
-Djava.io.tmpdir=C:\Tomcat
-Djavax.net.ssl.keyStore=C:\Tomcat\conf\KeyStore
-Djavax.net.ssl.keyStorePassword=changeit
-Djavax.net.ssl.keyStoreType=PKCS12
-Djavax.net.ssl.trustStore=C:\Tomcat\conf\TrustStore
-Djavax.net.ssl.trustStorePassword=changeit
-Djavax.net.debug=ssl,handshake,data,trustmanager,help

This will tell the JVM to use C:\tomcat\conf\KeyStore as the default KeyStore file for HTTPS connections, and C:\tomcat\conf\TrustStore as the default TrustStore file for HTTPS connections. Note: This change affects all web applications that access HTTPS connections from within Tomcat!

How do I communicate with the XDS Registry or XDS Repository?

There are three options. First, you can use sockets directly, and handle the HTTP and SOAP message parsing in your code. Secondly, you can use an HttpsURLConnection directly, and just handle the SOAP message parsing in your code, and finally, you can let a SOAP processor like Apache Axis handle all of the details for you.

First here is the Socket Factory for Java, if you want to do straight socket programming.

package net.ihe.iti.atna.net;

/*
 * Author: KBoone
 * Created: Monday, November 21, 2005 12:16:57 PM
 * Modified: Monday, November 21, 2005 12:16:57 PM
 */

import java.io.*;
import java.util.*;
import java.net.*;
import javax.net.*;
import javax.net.ssl.*;

/** This is a SocketFactory that will create TLS Client Sockets
 *  appropriate for use with the IHE ATNA Profile (see http://www.ihe.net).
 */
public class ATNASocketFactory extends SSLSocketFactory
{
    /** We layer ourselves over the default socket factory installed with J2S2. */
    static SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
    
    
    /** ATNA Supports two Cipher Suites, No encryption with RSA key exchange and SHA hashes,
     *  and AES 128 bit Block Ciphers.  If you have problems using the latter, you probably
     *  do not have the Java Unlimited Strength Jurisdiction Cryptography policy files installed.
     *  These can be found at http://java.sun.com/j2se/1.4.2/download.html or
     *  http://java.sun.com/j2se/1.5.0/download.html.
     *
     *  TBD: Make the initialization smarter, so that it sets suites based on
     *  what is supported by the JVM.
     */
    public static String[] suites = 
    {
        "TLS_RSA_WITH_AES_128_CBC_SHA", 
        "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"  // Diffie Hellman Key Exchange using DSS Certificate
        //, "SSL_RSA_WITH_NULL_SHA"   // 
    };
    
    /** By default, support NULL-SHA and AES128-SHA */
    public String[] getDefaultCipherSuites()
    {
        return suites;
    }
    
    /** But let this support anything the underlying J2SE factory 
        supports (for future extensibility)
     */
    public String[] getSupportedCipherSuites()
    {
        return factory.getSupportedCipherSuites();
    }
    
    /** Get a new ATNASocketFactory */
    public static SocketFactory getDefault()
    {
        return new ATNASocketFactory();
    }
    
    /** ATNA only supports the TLS protocol.  If you use anything else,
     *  the MESA test will not recognize the ClientHello message, and
     *  you will fail.
     */
    
    private static String enabledProtocols[] = { "TLSv1" };
    
    /** Take an existing socket, and set the default values correctly
     *  based on the requirements of ATNA.
     */
    private Socket defaultSettings(SSLSocket s)
    {
        s.setEnabledCipherSuites(getDefaultCipherSuites());
        s.setEnabledProtocols(enabledProtocols);
        return s;
    }
    
    /** Creates an unconnected socket. */
    public Socket createSocket() throws IOException
    {
        return defaultSettings((SSLSocket)factory.createSocket());
    }
    
    /** Creates a socket and connects it to the specified port number at the specified address. */
    public Socket createSocket(InetAddress host, int port)  throws IOException
    {
        return defaultSettings((SSLSocket)factory.createSocket());
    }
    /** Creates a socket and connect it to the specified remote address on the specified remote port. */
    public  Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
	throws IOException
    {
        return defaultSettings((SSLSocket)factory.createSocket(address, port, localAddress, localPort));
    }
    /** Creates a socket and connects it to the specified remote host at the specified remote port. */
    public Socket createSocket(String host, int port) throws IOException
    {
        return defaultSettings((SSLSocket)factory.createSocket(host, port));
    }
    /** Creates a socket and connects it to the specified remote host on the specified remote port. */
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) 
	throws IOException
    {
        return defaultSettings((SSLSocket)factory.createSocket(host, port, localHost, localPort));
    }
    
    /** Turns an existing socket on the specified remote host on the specified remote port. 
	into an SSL socket */
    public Socket createSocket(Socket s2, String host, int port, boolean autoClose)
        throws IOException
    {
        return defaultSettings((SSLSocket)factory.createSocket(s2, host, port, autoClose));
    }
}

Next, if you want to do Direct HTTP calls, use this little helper, and where you would normally write:

URLConnection c = url.openConnection();
Use:
URLConnection c = ATNAUtils.getATNAConnection(url);

Here's the code for ATNAUtils.

package net.ihe.iti.atna.util;

/*
 * Author: KBoone
 * Created: Monday, November 21, 2005 12:16:57 PM
 * Modified: Monday, November 21, 2005 12:16:57 PM
 */

import java.io.*;
import java.util.*;
import java.net.*;
import javax.net.*;
import javax.net.ssl.*;

import net.ihe.iti.atna.net.*;

public class ATNAUtils
{
    /** Return a URLConnection given a URL.  Configured it for
     *  ATNA support if necessary.
     */
    public static URLConnection getATNAConnection(URL url) throws IOException
    {
        URLConnection connection = url.openConnection();
        // If this URL is for HTTPS, then we need to use the ATNASocketFactory
        if (connection instanceof HttpsURLConnection)
        {
            HttpsURLConnection hCon = (HttpsURLConnection)connection;
            hCon.setSSLSocketFactory((ATNASocketFactory)ATNASocketFactory.getDefault());
            // TBD: For now we don't care about hostnames.  There should
            // be some way to verify them.
            hCon.setHostnameVerifier(
                new HostnameVerifier() {
                    public boolean verify(String hostname, SSLSession session)  
                    {
                        return true;
                    }
                }
            );
        }
        return connection;
    }

    /** Return a URLConnection given a URL.  Configured it for
     *  ATNA support if necessary.
     */
    public static URLConnection getATNAConnection(String url) throws MalformedURLException, IOException
    {
        return getATNAConnection(new URL(url));
    }
}

Finally is the Socket Factory for Axis. This depends on the Socket Factory for Java shown later.

Add the following line to your Tomcat startup Options (see How Do I set up Tomcat as an XDS Document Source or Consumer? above).

-Dorg.apache.components.net.SecureSocketFactory=net.ihe.iti.atna.net.axis.ATNASecureSocketFactory
package net.ihe.iti.atna.net.axis;

import net.ihe.iti.atna.net.ATNASocketFactory;
import org.apache.axis.components.net.*;
import java.util.Hashtable;
import java.io.IOException;

/** Extend the Apache Axis JSSE Secure Socket Factory so that when 
 *  an HTTPS URL is used as an endpoint, the SocketFactory returned will
 *  support ATNA requirements for TLS Communications.
 */
public class ATNASecureSocketFactory extends JSSESocketFactory  
{
    
    public ATNASecureSocketFactory(Hashtable attributes)
    {
        super(attributes);
    }

    /**
     * Initialize the SSLSocketFactory by setting the SSLSocketFactory
     * used to create sockets to the ATNASocketFactory.
     * @throws IOException
     */ 
    protected void initFactory() throws IOException {
        sslFactory = (ATNASocketFactory)ATNASocketFactory.getDefault();
    }   
}

Finally is the Socket Factory for Axis. This depends on the Socket Factory for Java shown later.

How do I Log a message when someone fails to connect to Tomcat?

Normally, when a TLS Connection fails to attach, Tomcat ignores it and goes on its merry way. However, under ATNA, it should send a message to the appropriate SysLog daemon. So you have to take control of the SSL Implementation that is used for your connector. To do this, add the line in bold to your connector.

   <Connector port="8443" acceptCount="100" 
     disableUploadTimeout="true" enableLookups="true" 
     scheme="https" secure="true" sslProtocol="TLS" clientauth="true" 
     keystoreFile="C:/tomcat/conf/KeyStore"
     keystorePass="changeit" 
     keystoreType="PKCS12"
     ciphers="SSL_RSA_WITH_NULL_SHA"
     maxProcessors="75" 
     maxThreads="75" 
     truststoreFile="C:/tomcat/conf/test_sys_1.cert"
     truststorePass="changeit"
     truststoreType="JKS"
     SLImplementation="net.ihe.iti.atna.net.tomcat.ATNAImplementation"
   />

Now, compile the following Java code and install the class files into C:\tomcat\server\classes\net\ihe\iti\atna\net\tomcat (that's assuming you've installed Tomcat at C:\tomcat). Oh, BTW, you need to put C:\tomcat\server\lib\tomcat-util.jar in your classpath when you compile.

package net.ihe.iti.atna.net.tomcat;

import java.util.Hashtable;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.net.*;
import org.apache.tomcat.util.net.jsse.JSSE14SocketFactory;
import org.apache.tomcat.util.net.jsse.JSSEImplementation;
import org.apache.tomcat.util.net.ServerSocketFactory;

/**
 *  Override a few methods in the JSSE14SocketFactory to
 *  support ATNA Logging in tomcat.
 */
public class ATNAImplementation extends JSSEImplementation
{
  private InetAddress address = null;
  private int port = 0;
  
  public ATNAImplementation() throws ClassNotFoundException
  {
    String p = System.getProperty(getClass().getName()+".address");
    try
    {
      address = (p == null || p.length() == 0) ? InetAddress.getLocalHost() : InetAddress.getByName(p);
    }
    catch (UnknownHostException uhex)
    {
      uhex.printStackTrace(System.err);
    }
    
    p = System.getProperty(getClass().getName()+".port");
    try
    {
      port = (p == null || p.length() == 0) ? 514 : Integer.parseInt(p);
    }
    catch (NumberFormatException nfex)
    {
      nfex.printStackTrace(System.err);
    }
  }
  
  public String getImplementationName() 
  {
    return "ATNAImplementation";
  }
  
  public ServerSocketFactory getServerSocketFactory()
  {
    return new ATNASocketFactory();
  }
  
  class ATNASocketFactory extends JSSE14SocketFactory
  {
    public void handshake(Socket sock) throws IOException 
    {
      try
      {
        super.handshake(sock);
      }
      catch (IOException ioex)
      {
        // We need to log the error.
        logATNAFailure(sock);   
      }
    }
    
    /** Write an IETF Format ATNA log message to syslog server */
    public void logATNAFailure(Socket s)
    {
      String msgText = "";
      
      try // protect the caller from seeing any exceptions
      {
        String hostName = s.getLocalAddress().getHostName();
        SimpleDateFormat sdf = new SimpleDateFormat("MMM dd HH:mm:ss ");
        Date now = new Date();
        StringBuffer b = new StringBuffer(sdf.format(now));
        if (b.charAt(4) == '0')
          b.setCharAt(4, ' ');
        
        DatagramSocket socket = new DatagramSocket();
        
        b = new StringBuffer("<" + (128 + 3) + ">" + b + hostName + " ");
        
        sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        
        /*  This is hard-coded XML, instead of using the nice atna audit classes.
         *  Why?  Because that way only this class needs to be dropped into tomcat/server/classes
         *  to be used by Tomcat.  
         */
        b.append("<AuditMessage>\n");
        b.append("  <EventIdentification");
        b.append(" EventActionCode='E' ");
        b.append(" EventDateTime='").append(sdf.format(now)).append("'");
        b.append(" EventOutcomeIndicator='8' >\n");
        b.append("  <EventID code='110113' codeSystemName='DCM' displayName='Security Alert' />\n");
        b.append("  <EventTypeCode code='110126' codeSystemName='DCM' displayName='Node Authentication' />\n");
        b.append("  </EventIdentification>\n");
        b.append("  <AuditSourceIdentification AuditSourceID='").append(this.getClass().getName()).append("' >\n");
        b.append("  <AuditSourceTypeCode code='4'/>\n");
        b.append("  </AuditSourceIdentification>\n");
        b.append("  <ParticipantObjectIdentification ParticipantObjectID='").
		append(s.getInetAddress().getHostAddress()).append("' ParticipantObjectTypeCode='2'>\n");
        b.append("  <ParticipantObjectIDTypeCode code='110182' codeSystemName='DCM' displayName='Node ID'  />\n");
        b.append("  <ParticipantObjectName>").append(s.getInetAddress().getHostName()).
		append("</ParticipantObjectName>\n");
        b.append("  </ParticipantObjectIdentification>\n");
        b.append("</AuditMessage>");
        
        msgText = b.toString();
        
        byte[] buf = null;
        buf = msgText.getBytes("UTF-8");
        
        if (address != null && port > 0 || port <= 65535)
        {   
          DatagramPacket packet = new DatagramPacket(buf, buf.length, address, port);
          socket.send(packet);
        }
        else
          System.err.println(msgText);
      }
      catch (Throwable t)
      {
        // It may occur, but even so, we don't want to throw an exception because
        // we are already inside one.  So we write the syslog message to STDOUT.
        System.err.println(msgText);
        // And give them the trace for this one.
        t.printStackTrace(System.err);
      }
    }
  }
}

How do I change the Syslog host and port?

The short answer is to read the code and figure it out, but I'll be nice, and tell you that you can add the following options:

-Dnet.ihe.iti.atna.net.tomcat.ATNAImplementation.address=SYSLOGSERVER_NAME
-Dnet.ihe.iti.atna.net.tomcat.ATNAImplementation.port=SYSLOGSERVER_PORT