package examples.security.rdbmsrealm;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import weblogic.security.acl.BasicRealm;
import weblogic.security.acl.User;
import weblogic.utils.encoders.BASE64Encoder;
/**
* This is the in-memory representation of a user from the database.
* The user has a name and password. The password may be one-way
* hashed; hashed passwords are stored in the database in the form
* <tt>{HASH}gobbledygook</tt>, where <tt>HASH</tt> is the name of the
* hashing algorithm, and <tt>gobbledygook</tt> is the hashed
* password. <p>
*
* You can store passwords either in hashed or plaintext form, and if
* you wish, you cvan vary this on a per-user basis (for example, use
* MD5 for one user, SHA for another, and a plaintext password for
* another user). However, for security and manageability reasons, we
* recommend using a single hashing algorithm for all passwords, and
* not storing any plaintext passwords in the database. <p>
*
* This class has a <tt>main</tt> method, which you can use to
* generate hashed passwords from plaintext passwords. The hashed
* passwords can then be stored in your database.
*
* @author Copyright (c) 1998-2000 by BEA Systems, Inc. All Rights Reserved.
*/
class RDBMSUser
extends User
{
/**
* The default password-generation algorithm.
*/
protected static final String ALGORITHM = "SHA";
/**
* The realm that created this user object.
*/
private transient RDBMSRealm realm;
/**
* This user's password. If this is hashed, the md field will
* contain an instance of an object that performs the hashing
* algorithm.
*/
private transient String passwd;
/**
* The digest algorithm used to one-way hash this user's password.
* If the password is not hashed with a known algorithm, or is in
* plain form, this will be null.
*/
private transient MessageDigest md;
/**
* Create a user with the given name and (maybe hashed) password,
* from the given realm.
*/
RDBMSUser(String name, String passwd, RDBMSRealm realm)
{
super(name);
this.realm = realm;
// Check to see if the password was stored in hashed form, and if
// it was, whether we can use that hashing algorithm.
if (passwd != null)
{
int rightCurly = passwd.indexOf("}");
if (rightCurly > 0 && passwd.charAt(0) == '{')
{
this.passwd = passwd.substring(rightCurly + 1);
String algorithm = passwd.substring(1, rightCurly);
try
{
md = MessageDigest.getInstance(algorithm.toUpperCase());
}
catch (NoSuchAlgorithmException e)
{
if (realm.log != null)
{
realm.log.error("digest algorithm \"" + algorithm +
"\" not found - assuming plaintext password");
} else {
System.err.println("Error: digest algorithm \"" + algorithm +
"\" not found - assuming plaintext password");
}
}
} else {
this.passwd = passwd;
this.md = null;
}
}
}
/**
* Return the realm that created this object.
*/
public BasicRealm getRealm()
{
return realm;
}
/**
* Hash the given plaintext with the given digest algorithm, and
* base64-encode the result.
*
* @param md message digest algorithm to hash with
* @param plaintext text to hash
* @return base64-encoded hashed text
*/
static protected String hash(MessageDigest md, String plaintext)
{
BASE64Encoder enc = new BASE64Encoder();
return enc.encodeBuffer(md.digest(plaintext.getBytes()));
}
/**
* Check a plaintext password against this user's password. If the
* object containing the password is not known, authentication will
* fail.
*
* @param plaintext the plaintext password to check
* @return true if matched, false otherwise
*/
boolean authenticate(String plaintext)
{
String hashed = md != null ? hash(md, plaintext) : plaintext;
return hashed.equals(passwd);
}
/**
* Hash passwords according to the given algorithm. Plaintext
* passwords are read from stdin, and the encrypted passwords are
* printed to stdout. If no algorithm is specified on the command
* line, the one specified in ALGORITHM is used.
*
* @see #ALGORITHM
*/
public static void main(String[] args)
throws IOException
{
String algorithm = (args.length >= 1 ? args[0] : ALGORITHM).toUpperCase();
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
MessageDigest md = null;
String prefix = null;
String plaintext;
try
{
md = MessageDigest.getInstance(algorithm);
}
catch (NoSuchAlgorithmException e)
{
// ignore
}
if (md == null)
{
System.err.println("Error: unknown algorithm \"" + algorithm + "\"");
System.exit(1);
}
System.err.println("Enter plaintext passwords, separated by newlines.");
while ((plaintext = r.readLine()) != null)
{
String passwd = "{" + algorithm + "}" + hash(md, plaintext);
System.out.println(passwd);
if (System.out.checkError())
{
throw new IOException("output error");
}
}
r.close();
}
}