Hi,

I've been playing around with Tomcat 3.2.1 as we have several production
servers using it and was concerned by the way the passwords were stored
in tomcat-users.xml.

The included patch modifies SimplesRealm.java
(org.apache.tomcat.request.SimpleRealm) so it can correctly manage a
tomcat-users.xml file whose passwords are encrypted.

The method used to handle encryption is java.security.MessageDigest,
therefore all algorithms known by this class (without the use of an
external Provider) can be used, mainly MD5 and SHA.

All passwords in tomcat-users.xml must be encrypted using the same
algorithm (or no algorithm if so choosen). The algorithm of choice is
specified in the declaration of
the SimpleRealm RequestInterceptor as follows:

      <RequestInterceptor 
       className="org.apache.tomcat.request.SimpleRealm" 
       debug="1" crypt="MD5" />

The SimpleRealm request interceptor then expects all tomcat-users.xml
passwords to be
encrypted using the specified algorithm, comparison is case insensitive
(for the encrypted part).

If you choose not to use encryption, simply omit the crypt attribute in
the RequestInterceptor element.

As I am not a subscriber of the tomcat-dev mailing list please CC me
when replying to my message.

Any comment welcome about this patch.

Best regards,

Mathias Herberts.
--- org/apache/tomcat/request/SimpleRealm.java.orig     Fri Feb  9 21:42:02 2001
+++ org/apache/tomcat/request/SimpleRealm.java  Fri Feb  9 22:36:49 2001
@@ -66,6 +66,7 @@
 import java.io.*;
 import java.net.*;
 import java.util.*;
+import java.security.*;
 import org.xml.sax.*;
 
 /**
@@ -84,6 +85,9 @@
     ContextManager cm;
     int reqRolesNote;
     
+    // MessageDigest algorithm
+    String crypt;
+
     public SimpleRealm() {
     }
 
@@ -112,6 +116,7 @@
            memoryRealm = new MemoryRealm(ctx);
            try {
                memoryRealm.readMemoryRealm(ctx);
+               memoryRealm.crypt = crypt;
            } catch(Exception ex ) {
                ex.printStackTrace();
                memoryRealm=null;
@@ -166,6 +171,10 @@
        if( debug > 0 ) log( "UnAuthorized " + roles[0] );
        return 401;
     }
+
+    public void setCrypt( String c ) {
+       crypt = c;
+    }
 }
 
 class MemoryRealm {
@@ -177,6 +186,9 @@
     Hashtable userRoles= new Hashtable();
     Context ctx;
     int debug=0;
+
+    // MessageDigest used to encrypt the passwords
+    String crypt;
     
     MemoryRealm(Context ctx) {
        this.ctx=ctx;
@@ -218,7 +230,45 @@
     public boolean checkPassword( String user, String pass ) {
        if( user==null ) return false;
        if( debug > 0 ) ctx.log( "check " + user+ " " + pass + " " + passwords.get( 
user ));
-       return pass.equals( (String)passwords.get( user ) );
+       if( crypt==null ) {
+           return pass.equals( (String)passwords.get( user ) );
+       } else {
+           return checkMDPassword( user, pass );
+       }
+    }
+
+    public boolean checkMDPassword( String user, String pass ) {
+       MessageDigest md;
+
+       if( crypt==null ) {
+           if( debug > 0 ) ctx.log( "MessageDigest algorithm not set" );
+           return false;
+       }
+
+       try {
+           md = MessageDigest.getInstance( crypt );
+       } catch( NoSuchAlgorithmException e ) {
+           if( debug > 0 ) ctx.log( "Unknown MessageDigest algorithm " + crypt );
+           return false;
+       }
+       
+       if( md!=null ) {
+           String s = "";
+           byte a[] = md.digest (pass.getBytes());
+
+           for( int i = 0; i < a.length; i++ ) {
+               s = s.concat( Integer.toHexString( (0x100 | a[i]) & 0x1ff 
+).toUpperCase().substring( 1 ) );
+           }
+
+           if( ((String)passwords.get( user )).toUpperCase().compareTo( s )== 0) {
+               return true;
+           } else {
+               return false;
+           }
+       } else {
+           if( debug > 0 ) ctx.log( "Failed to create MessageDigest" );
+           return false;
+       }
     }
 
     public String[] getUserRoles( String user ) {

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to