package examples.security.audit;
import java.net.Socket;
import java.security.Principal;
import java.security.acl.Acl;
import java.security.acl.Permission;
import java.util.Vector;
import weblogic.logging.LogOutputStream;
import weblogic.security.X509;
import weblogic.security.acl.DefaultUserInfoImpl;
import weblogic.security.acl.SSLUserInfo;
import weblogic.security.acl.User;
import weblogic.security.acl.UserInfo;
import weblogic.security.audit.AuditProvider;
/**
* Simple implementation of the audit SPI. This class just dumps the
* pertinent information in the server log file. It should be
* straightforward to write an alternate implementation that logs
* events to an RDBMS, for example.
*
* @author Copyright (c) 1999-2000 by BEA Systems, Inc. All Rights Reserved.
*/
public class LogAuditProvider
implements AuditProvider
{
protected LogOutputStream log;
private int lastCount = 0;
private String lastMessage = null;
/**
* No-arg constructor, as required by the audit SPI.
*/
public LogAuditProvider()
{
log = new LogOutputStream("Audit");
log.info("Security auditing started");
}
public void authenticateUser(String subsystem, UserInfo info, User result)
{
if (filterAuthenticateUser(subsystem, info, result))
{
String user = info.getName();
String credential = null;
if (info instanceof DefaultUserInfoImpl)
{
DefaultUserInfoImpl dinfo = (DefaultUserInfoImpl) info;
Vector credentials = new Vector(1);
// Indicate what kind of credentials we received.
if (dinfo.hasPassword())
{
credentials.addElement("password");
}
if (dinfo.hasCertificates())
{
credentials.addElement("certificates");
}
if (dinfo instanceof SSLUserInfo)
{
credentials.addElement("SSL certificates");
}
credential = credentials.size() > 0
? (weblogic.utils.enumerations.EnumerationUtils.toString
(credentials.elements(), " + "))
: "nothing";
} else {
credential = "unknown";
}
dump(subsystem, "user auth",
"user=" + str(user) + ", credentials=" + credential + ", " +
(result != null ? "SUCCESS" : "FAILURE"));
}
}
/**
* You can override this method in a subclass if you want to
* conditionally filter authenticateUser events.
*
* @return whether to log this event
*/
protected boolean filterAuthenticateUser(String subsystem, UserInfo info,
User result)
{
return true;
}
public void checkPermission(String subsystem, Acl acl, Principal principal,
Permission permission, boolean result)
{
if (filterCheckPermission(subsystem, acl, principal, permission, result))
{
dump(subsystem, "check perm",
"acl=" + str(acl != null ? acl.getName() : null) +
", principal=" + str(principal != null ? principal.getName() : null) +
", permission=" + str(permission) + ", " +
(result ? "ALLOW" : "DISALLOW"));
}
}
/**
* You can override this method in a subclass if you want to
* conditionally filter checkPermission events.
*
* @return whether to log this event
*/
protected boolean filterCheckPermission(String subsystem, Acl acl,
Principal principal,
Permission permission, boolean result)
{
return true;
}
public void certificateInvalid(String subsystem, Object source, X509 cert)
{
if (filterCertificateInvalid(subsystem, source, cert))
{
String origin = "unknown";
if (source instanceof Socket)
{
Socket sock = (Socket) source;
origin = sock.getInetAddress().getHostName() + ":" +
sock.getPort();
}
else if (source instanceof String)
{
origin = (String) source;
}
String reason = cert != null ? cert.explain() : "no certificate presented";
dump(subsystem, "invalid X.509 certificate", "source is " + origin + ", " +
(reason != null ? reason : "cause unknown"));
}
}
/**
* You can override this method in a subclass if you want to
* conditionally filter certificateInvalid events.
*
* @return whether to log this event
*/
protected boolean filterCertificateInvalid(String subsystem, Object source,
X509 cert)
{
return true;
}
public void rootCAInvalid(String subsystem, Object source, X509 cert)
{
if (filterRootCAInvalid(subsystem, source, cert))
{
String origin = "unknown";
if (source instanceof Socket)
{
Socket sock = (Socket) source;
origin = sock.getInetAddress().getHostName() + ":" +
sock.getPort();
}
else if (source instanceof String)
{
origin = (String) source;
}
dump(subsystem, "invalid X.509 root CA", "source is " + origin);
}
}
/**
* You can override this method in a subclass if you want to
* conditionally filter rootCAInvalid events.
*
* @return whether to log this event
*/
protected boolean filterRootCAInvalid(String subsystem, Object source,
X509 cert)
{
return true;
}
/**
* Wrap an object in double quotes, if its value is not null,
* otherwise return the string "null".
*/
private static final String str(Object thing)
{
return thing != null ? ("\"" + thing + "\"") : "null";
}
protected void dump(String subsystem, String op, String message)
{
String msg = "[" + subsystem + "] " + op + ": " + message;
if (lastMessage == null)
{
log.info(msg);
lastMessage = msg;
lastCount = 0;
}
else if (lastMessage.equals(msg))
{
lastCount += 1;
} else {
if (lastCount == 1)
{
log.info(lastMessage);
}
else if (lastCount > 1)
{
log.info("(last audit message repeated " + + lastCount + " times)");
}
lastCount = 0;
log.info(msg);
lastMessage = msg;
}
}
}