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]