package org.w3c.jigsaw.auth;
import java.io.*;
import java.util.*;
import java.net.*;
import org.w3c.tools.resources.*;
import org.w3c.jigsaw.http.*;
import org.w3c.jigsaw.html.*;
import org.w3c.tools.codec.* ;
import org.w3c.www.http.*;
import org.w3c.tools.resources.ProtocolException;
class BasicAuthContextException extends Exception {
BasicAuthContextException (String msg) {
super (msg) ;
}
}
class BasicAuthContext {
String user = null ;
String password = null ;
String cookie = null ;
public String toString() {
return user+":"+password;
}
BasicAuthContext (Request request)
throws BasicAuthContextException, ProtocolException
{
HttpCredential credential = null;
credential = (request.isProxy()
? request.getProxyAuthorization()
: request.getAuthorization());
if ( ! credential.getScheme().equalsIgnoreCase("Basic") ) {
String msg = ("Invalid authentication scheme \""
+ credential.getScheme()
+ " expecting \"Basic\"");
throw new BasicAuthContextException (msg) ;
}
String decoded = null ;
this.cookie = credential.getAuthParameter("cookie");
try {
Base64Decoder b = new Base64Decoder (cookie) ;
decoded = b.processString() ;
} catch (Base64FormatException e) {
String msg = "Invalid BASE64 encoding of credentials." ;
throw new BasicAuthContextException (msg) ;
}
int icolon = decoded.indexOf (':') ;
if ( (icolon > 0) && (icolon+1 < decoded.length()) ) {
this.user = decoded.substring (0, icolon) ;
this.password = decoded.substring (icolon+1) ;
} else {
String msg = "Invalid credentials syntax in " + decoded ;
throw new BasicAuthContextException (msg) ;
}
}
}
public class GenericAuthFilter extends AuthFilter {
protected static int ATTR_ALLOWED_USERS = -1 ;
protected static int ATTR_ALLOWED_GROUPS = -1 ;
static {
Attribute a = null ;
Class c = null ;
try {
c = Class.forName("org.w3c.jigsaw.auth.GenericAuthFilter");
} catch (Exception ex) {
ex.printStackTrace() ;
System.exit(1) ;
}
a = new StringArrayAttribute("users"
, null
, Attribute.EDITABLE) ;
ATTR_ALLOWED_USERS = AttributeRegistry.registerAttribute(c, a) ;
a = new StringArrayAttribute("groups"
, null
, Attribute.EDITABLE);
ATTR_ALLOWED_GROUPS = AttributeRegistry.registerAttribute(c, a) ;
}
protected IPMatcher ipmatcher = null ;
protected RealmsCatalog catalog = null ;
protected ResourceReference rr_realm = null ;
protected String loaded_realm = null ;
protected HttpChallenge challenge = null;
protected synchronized void acquireRealm() {
if ( catalog == null ) {
httpd server = (httpd)
((FramedResource) getTargetResource()).getServer() ;
catalog = server.getRealmsCatalog() ;
}
String name = getRealm() ;
if ( name == null )
return ;
if ((rr_realm != null) && name.equals(loaded_realm))
return ;
rr_realm = catalog.loadRealm(name) ;
if (rr_realm != null) {
try {
AuthRealm realm = (AuthRealm) rr_realm.lock();
Enumeration enum = realm.enumerateUserNames() ;
if (enum.hasMoreElements())
ipmatcher = new IPMatcher() ;
while (enum.hasMoreElements()) {
String uname = (String) enum.nextElement() ;
ResourceReference rr_user = realm.loadUser(uname) ;
try {
AuthUser user = (AuthUser) rr_user.lock();
short ips[][] = user.getIPTemplates() ;
if ( ips != null ) {
for (int i = 0 ; i < ips.length ; i++)
ipmatcher.add(ips[i], rr_user) ;
}
} catch (InvalidResourceException ex) {
System.out.println("Invalid user reference : "+uname);
} finally {
rr_user.unlock();
}
}
} catch (InvalidResourceException ex) {
} finally {
rr_realm.unlock();
}
}
}
@return
protected synchronized boolean checkRealm() {
acquireRealm() ;
return (ipmatcher != null) ;
}
public String[] getAllowedUsers() {
return (String[]) getValue(ATTR_ALLOWED_USERS, null) ;
}
public String[] getAllowedGroups() {
return (String[]) getValue(ATTR_ALLOWED_GROUPS, null) ;
}
@param ipaddr@return
public synchronized ResourceReference lookupUser (InetAddress ipaddr) {
if ( ipmatcher == null )
acquireRealm() ;
return (ResourceReference) ipmatcher.lookup(ipaddr.getAddress()) ;
}
@param name@return
public synchronized ResourceReference lookupUser (String name) {
if ( rr_realm == null )
acquireRealm() ;
try {
AuthRealm realm = (AuthRealm) rr_realm.lock();
return realm.loadUser(name) ;
} catch (InvalidResourceException ex) {
return null;
} finally {
rr_realm.unlock();
}
}
@param ctxt@return
protected ResourceReference checkBasicAuth(BasicAuthContext ctxt) {
ResourceReference rr_user = (ResourceReference)lookupUser(ctxt.user) ;
if (rr_user != null) {
try {
AuthUser user = (AuthUser) rr_user.lock();
if ( user == null )
return null ;
if ( ! user.definesAttribute("password") ) {
return rr_user;
} else {
return user.getPassword().equals(ctxt.password) ? rr_user : null ;
}
} catch (InvalidResourceException ex) {
return null;
} finally {
rr_user.unlock();
}
}
return null;
}
@return
protected boolean checkUser(AuthUser user) {
String allowed_users[] = getAllowedUsers() ;
if ( allowed_users != null ) {
for (int i = 0 ; i < allowed_users.length ; i++) {
if (allowed_users[i].equals(user.getName()))
return true ;
}
}
String allowed_groups[] = getAllowedGroups() ;
if ( allowed_groups != null ) {
String ugroups[] = user.getGroups() ;
if ( ugroups != null ) {
for (int i = 0 ; i < ugroups.length ; i++) {
for (int j = 0 ; j < allowed_groups.length ; j++) {
if ( allowed_groups[j].equals(ugroups[i]) )
return true ;
}
}
}
}
if ((allowed_users == null) && (allowed_groups == null))
return true ;
return false ;
}
public void setValue(int idx, Object value) {
super.setValue(idx, value);
if ( idx == ATTR_REALM ) {
challenge = HttpFactory.makeChallenge("Basic");
challenge.setAuthParameter("realm", getRealm());
}
}
@param request
public void authenticate (Request request)
throws ProtocolException
{
if ( ! checkRealm() )
return ;
Client client = request.getClient() ;
if ( client == null )
return ;
boolean ipchecked = false ;
ResourceReference rr_user = lookupUser(client.getInetAddress());
if (rr_user != null) {
try {
AuthUser user = (AuthUser) rr_user.lock();
if ( user != null ) {
ipchecked = true ;
if ( ! user.definesAttribute("password") && checkUser(user)) {
request.setState(STATE_AUTHUSER, user.getName()) ;
request.setState(STATE_AUTHTYPE, "ip");
return ;
}
}
} catch (InvalidResourceException ex) {
} finally {
rr_user.unlock();
}
}
if ((request.hasAuthorization() && ! request.isProxy())
|| (request.isProxy() && request.hasProxyAuthorization())) {
BasicAuthContext ctxt = null ;
try {
ctxt = new BasicAuthContext(request);
} catch (BasicAuthContextException ex) {
ctxt = null;
}
if ( ctxt != null ) {
rr_user = checkBasicAuth(ctxt) ;
if (rr_user != null) {
try {
AuthUser user = (AuthUser) rr_user.lock();
if ((user != null) && checkUser(user)) {
boolean iprequired = user.definesAttribute("ipaddress") ;
if ( ( ! iprequired) || ipchecked ) {
request.setState(STATE_AUTHUSER, ctxt.user);
request.setState(STATE_AUTHTYPE, "Basic") ;
return ;
}
}
} catch (InvalidResourceException ex) {
} finally {
rr_user.unlock();
}
}
}
}
Reply e = null;
if ( request.isProxy() ) {
e = request.makeReply(HTTP.PROXY_AUTH_REQUIRED);
e.setProxyAuthenticate(challenge);
} else {
e = request.makeReply(HTTP.UNAUTHORIZED);
e.setWWWAuthenticate (challenge);
}
HtmlGenerator g = new HtmlGenerator("Unauthorised");
g.append ("<h1>Unauthorised access</h1>"
+ "<p>You are denied access to this resource.");
e.setStream(g);
throw new HTTPException (e);
}
public void initialize(Object values[]) {
super.initialize(values) ;
if ( getRealm() != null ) {
challenge = HttpFactory.makeChallenge("Basic");
challenge.setAuthParameter("realm", getRealm());
}
}
}