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