Annotation of java/classes/org/w3c/jigsaw/acl/AclFilter.java, revision 1.13
1.1 bmahe 1: // AclFilter.java
1.13 ! ylafon 2: // $Id: AclFilter.java,v 1.12 2012/06/16 15:48:44 ylafon Exp $
1.1 bmahe 3: // (c) COPYRIGHT MIT, INRIA and Keio, 1999.
4: // Please first read the full copyright statement in file COPYRIGHT.html
1.8 ylafon 5:
1.1 bmahe 6: package org.w3c.jigsaw.acl;
7:
1.2 bmahe 8: import java.security.Principal;
9: import java.security.acl.Permission;
10: import java.security.acl.Acl;
11:
12: import org.w3c.jigsaw.html.HtmlGenerator;
13: import org.w3c.jigsaw.http.HTTPException;
14: import org.w3c.jigsaw.http.Reply;
15: import org.w3c.jigsaw.http.Request;
16:
17: import org.w3c.tools.resources.Attribute;
18: import org.w3c.tools.resources.AttributeRegistry;
19: import org.w3c.tools.resources.BooleanAttribute;
20: import org.w3c.tools.resources.IntegerAttribute;
21: import org.w3c.tools.resources.LookupResult;
22: import org.w3c.tools.resources.LookupState;
23: import org.w3c.tools.resources.ProtocolException;
1.5 bmahe 24: import org.w3c.tools.resources.ResourceFrame;
1.1 bmahe 25: import org.w3c.tools.resources.ResourceFilter;
1.2 bmahe 26: import org.w3c.tools.resources.RequestInterface;
27: import org.w3c.tools.resources.ReplyInterface;
1.3 bmahe 28: import org.w3c.tools.resources.StringAttribute;
1.2 bmahe 29:
30: import org.w3c.www.http.HTTP;
31: import org.w3c.www.http.HttpChallenge;
1.1 bmahe 32:
33: /**
1.12 ylafon 34: * @author Benoît Mahé (bmahe@w3.org)
1.13 ! ylafon 35: * @version $Revision: 1.12 $
1.1 bmahe 36: */
37: public class AclFilter extends ResourceFilter {
1.3 bmahe 38:
1.2 bmahe 39: /**
40: * Attribute index - Security level 0=Basic 1=Digest...
41: */
42: protected static int ATTR_SECURITY_LEVEL = -1;
43: /**
1.3 bmahe 44: * Attribute index - The algorithm used
45: */
1.12 ylafon 46: protected static int ATTR_ALGORITHM = -1;
1.3 bmahe 47: /**
48: * Attribute index - The nonce time to live (in seconds)
49: */
1.12 ylafon 50: protected static int ATTR_NONCE_TTL = -1;
1.3 bmahe 51: /**
1.2 bmahe 52: * Attribute index - And or Or for multiple Acls
53: */
54: protected static int ATTR_STRICT_ACL_MERGE_POLICY = -1;
55: /**
56: * Attribute index - Is caching allowed by a shared cache ?
57: */
58: protected static int ATTR_SHARED_CACHABILITY = -1;
59: /**
60: * Attribute index - Is caching allowed in private cache ?
61: */
62: protected static int ATTR_PRIVATE_CACHABILITY = -1;
63: /**
64: * Attribute index - Is public caching of protected documents allowed ?
65: */
66: protected static int ATTR_PUBLIC_CACHABILITY = -1;
1.11 ylafon 67: /**
68: * Attribute index - Do we enable workarounds ?
69: */
70: protected static int ATTR_LENIENT = -1;
1.2 bmahe 71:
72: /**
73: * The JAcl class.
74: */
1.13 ! ylafon 75: protected static Class<?> JAcl_class = null;
1.2 bmahe 76:
1.3 bmahe 77: protected SecurityLevel security = null;
78:
1.2 bmahe 79: static {
1.12 ylafon 80: Attribute a = null;
1.13 ! ylafon 81: Class<?> c = null;
1.12 ylafon 82: try {
83: c = Class.forName("org.w3c.jigsaw.acl.AclFilter");
84: JAcl_class = Class.forName("org.w3c.jigsaw.acl.JAcl");
85: } catch (Exception ex) {
86: ex.printStackTrace();
87: System.exit(1);
88: }
89: // security level
90: a = new IntegerAttribute("security-level",
91: new Integer(0),
92: Attribute.EDITABLE);
93: ATTR_SECURITY_LEVEL = AttributeRegistry.registerAttribute(c, a);
94: // do we use a strict acl merge policy
95: a = new BooleanAttribute("strict-acl-merge-policy"
96: , Boolean.TRUE
97: , Attribute.EDITABLE);
98: ATTR_STRICT_ACL_MERGE_POLICY =
99: AttributeRegistry.registerAttribute(c, a);
100: // The algorithm used for digest and checksum
101: a = new StringAttribute("algorithm"
102: , null
103: , Attribute.EDITABLE);
104: ATTR_ALGORITHM = AttributeRegistry.registerAttribute(c, a);
105: a = new IntegerAttribute("nonce_ttl"
106: , new Integer(300)
107: , Attribute.EDITABLE);
108: ATTR_NONCE_TTL = AttributeRegistry.registerAttribute(c, a);
109: // Can protected documents be saved in shared cache ?
110: a = new BooleanAttribute("shared-cachability"
111: , Boolean.FALSE
112: , Attribute.EDITABLE);
113: ATTR_SHARED_CACHABILITY = AttributeRegistry.registerAttribute(c, a);
114: // Can protected documents be shared in private cache ?
115: a = new BooleanAttribute("private-cachability"
116: , Boolean.FALSE
117: , Attribute.EDITABLE);
118: ATTR_PRIVATE_CACHABILITY = AttributeRegistry.registerAttribute(c, a);
119: // Can protected documents be publicly cached ?
120: a = new BooleanAttribute("public-cachability"
121: , Boolean.FALSE
122: , Attribute.EDITABLE);
123: ATTR_PUBLIC_CACHABILITY = AttributeRegistry.registerAttribute(c, a);
124: // Are we lenient in the way we check things ?
125: // related to enabling/disabling workarounds because of some
126: // implementations
127: a = new BooleanAttribute("lenient"
128: , Boolean.FALSE
129: , Attribute.EDITABLE);
130: ATTR_LENIENT = AttributeRegistry.registerAttribute(c, a);
1.2 bmahe 131: }
132:
133: /**
134: * Get the security level.
1.12 ylafon 135: *
1.2 bmahe 136: * @return an integer;
1.12 ylafon 137: */
1.2 bmahe 138: public int getSecurityLevel() {
1.12 ylafon 139: return getInt(ATTR_SECURITY_LEVEL, 0);
1.2 bmahe 140: }
141:
142: /**
1.3 bmahe 143: * Get the algorithm used
144: */
145: public String getAlgorithm() {
1.12 ylafon 146: return (String) getValue(ATTR_ALGORITHM, "MD5");
1.3 bmahe 147: }
148:
149: public int getNonceTTL() {
1.12 ylafon 150: return getInt(ATTR_NONCE_TTL, 300);
1.3 bmahe 151: }
152:
153: /**
1.2 bmahe 154: * Returns true if we have a strict acl merge policy.
1.12 ylafon 155: *
1.2 bmahe 156: * @return a boolean.
157: */
158: public boolean isStrictAclMergePolicy() {
1.12 ylafon 159: return getBoolean(ATTR_STRICT_ACL_MERGE_POLICY, true);
1.2 bmahe 160: }
161:
162: /**
163: * Is this document publicly cachable ?
1.12 ylafon 164: *
1.2 bmahe 165: * @return A boolean.
166: */
167: public boolean getPublicCachability() {
1.12 ylafon 168: return getBoolean(ATTR_PUBLIC_CACHABILITY, false);
1.2 bmahe 169: }
170:
171: /**
172: * Is this document cachable in private caches ?
1.12 ylafon 173: *
1.2 bmahe 174: * @return A boolean.
175: */
176: public boolean getPrivateCachability() {
1.12 ylafon 177: return getBoolean(ATTR_PRIVATE_CACHABILITY, false);
1.2 bmahe 178: }
179:
180: /**
181: * Is this document cachable in shared caches ?
1.12 ylafon 182: *
1.2 bmahe 183: * @return A boolean.
184: */
185: public boolean getSharedCachability() {
1.12 ylafon 186: return getBoolean(ATTR_SHARED_CACHABILITY, false);
1.2 bmahe 187: }
188:
1.11 ylafon 189: /**
1.12 ylafon 190: * Are we lenient in the way we check things?
1.11 ylafon 191: * can be read as "Do we enable workarounds for broken implementations?"
1.12 ylafon 192: *
1.11 ylafon 193: * @return A boolean.
194: */
195: public boolean isLenient() {
1.12 ylafon 196: return getBoolean(ATTR_LENIENT, false);
1.11 ylafon 197: }
198:
1.2 bmahe 199: protected JAcl[] getAcls() {
1.12 ylafon 200: ResourceFrame frames[] = collectFrames(JAcl_class);
201: JAcl acls[] = new JAcl[frames.length];
202: for (int i = 0; i < frames.length; i++)
203: acls[i] = (JAcl) frames[i];
204: return acls;
1.2 bmahe 205: }
206:
207: /**
1.12 ylafon 208: * Authenticate the given request for the given client.
1.2 bmahe 209: * This method is invoked prior to any request handling on its target
1.12 ylafon 210: * entity. If the used authentication method allows so, AuthFilters
1.2 bmahe 211: * should set the <strong>authuser</strong> attribute of the request.
1.12 ylafon 212: *
1.13 ! ylafon 213: * @param ls the LookupState containing the The request.
! 214: * @param lr the Lookup Result
1.12 ylafon 215: * @throws ProtocolException If authentication failed.
1.2 bmahe 216: */
217:
218: public boolean lookup(LookupState ls, LookupResult lr)
1.12 ylafon 219: throws ProtocolException {
220: JAcl acls[] = getAcls();
221: if ((acls == null) || (ls.getRequest() == null)) {
222: return false;
223: }
224: authenticate((Request) ls.getRequest(), acls);
225: return false;
1.2 bmahe 226: }
227:
228: /**
229: * Authenticate the given request.
1.12 ylafon 230: *
1.2 bmahe 231: * @param request The request to be authentified.
1.12 ylafon 232: * @param acls The Access Control List array.
233: * @throws org.w3c.tools.resources.ProtocolException
234: * if authentication
235: * failed
236: */
237: protected void authenticate(Request request, JAcl acls[])
238: throws ProtocolException {
239: Permission perm = new HTTPPermission(request);
240: Principal princ = security.getPrincipal(request, getAlgorithm());
241: boolean strict = isStrictAclMergePolicy();
242: boolean authorized = false;
243: Acl acl = acls[0];
244:
245: if (princ != null) {
246: boolean check;
247: if (strict) {
248: authorized = true;
249: for (JAcl jacl : acls) {
250: check = jacl.checkPermission(princ, perm);
251: if (!check) {
252: authorized = false;
253: acl = jacl;
254: break;
255: }
256: }
257: } else {
258: for (JAcl jacl : acls) {
259: if (jacl.checkPermission(princ, perm)) {
260: authorized = true;
261: break;
262: }
263: }
264: }
265: }
266:
267: if (!authorized) {
268: HttpChallenge challenge =
269: security.getChallenge(acl.getName(), princ);
270: Reply e = null;
271: if (request.isProxy()) {
272: e = request.makeReply(HTTP.PROXY_AUTH_REQUIRED);
273: e.setProxyAuthenticate(challenge);
274: } else {
275: e = request.makeReply(HTTP.UNAUTHORIZED);
276: e.setWWWAuthenticate(challenge);
277: }
278: HtmlGenerator g = new HtmlGenerator("Unauthorized");
279: g.append("<h1>Unauthorized access</h1>" +
280: "<p>You are denied access to this resource.");
281: e.setStream(g);
282: request.skipBody();
283: throw new HTTPException(e);
284: } else {
285: security.updateRequestStates(request, princ);
286: }
287:
1.2 bmahe 288: }
1.8 ylafon 289:
1.2 bmahe 290: /**
291: * Add the appropriate cache control directives on the way back.
1.12 ylafon 292: *
1.2 bmahe 293: * @param request The request that has been processed.
1.12 ylafon 294: * @param reply The original reply.
1.2 bmahe 295: * @return Always <strong>null</strong>.
296: */
297: public ReplyInterface outgoingFilter(RequestInterface request,
1.12 ylafon 298: ReplyInterface reply) {
299: Reply rep = (Reply) reply;
300: if (getPrivateCachability()) {
301: rep.setPrivate(true);
302: } else if (getSharedCachability()) {
303: rep.setProxyRevalidate(true);
304: } else if (getPublicCachability()) {
305: rep.setPublic(true);
306: }
307: security.updateReply(rep, (Request) request);
308: return null;
1.3 bmahe 309: }
310:
311: /**
312: * Catch set value to maintain cached values.
313: */
314: public void setValue(int idx, Object value) {
1.12 ylafon 315: super.setValue(idx, value);
316: if ((idx == ATTR_SECURITY_LEVEL) || (idx == ATTR_ALGORITHM)
317: || (idx == ATTR_LENIENT)) {
318: security = SecurityLevel.getSecurityLevel(this);
319: }
1.3 bmahe 320: }
1.8 ylafon 321:
1.3 bmahe 322: /**
323: * Initialize the filter.
324: */
325: public void initialize(Object values[]) {
1.12 ylafon 326: super.initialize(values);
327: security = SecurityLevel.getSecurityLevel(this);
1.2 bmahe 328: }
1.1 bmahe 329: }
Webmaster