Source Code Cross Referenced for RealmBase.java in  » Sevlet-Container » tomcat-catalina » org » apache » catalina » realm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » tomcat catalina » org.apache.catalina.realm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999,2004 The Apache Software Foundation.
0003:         * 
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         * 
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.apache.catalina.realm;
0018:
0019:        import java.beans.PropertyChangeListener;
0020:        import java.beans.PropertyChangeSupport;
0021:        import java.io.IOException;
0022:        import java.security.MessageDigest;
0023:        import java.security.NoSuchAlgorithmException;
0024:        import java.security.Principal;
0025:        import java.security.cert.X509Certificate;
0026:        import java.util.ArrayList;
0027:
0028:        import javax.management.MBeanRegistration;
0029:        import javax.management.MBeanServer;
0030:        import javax.management.ObjectName;
0031:        import javax.servlet.http.HttpServletRequest;
0032:        import javax.servlet.http.HttpServletResponse;
0033:
0034:        import org.apache.catalina.Container;
0035:        import org.apache.catalina.Context;
0036:        import org.apache.catalina.HttpRequest;
0037:        import org.apache.catalina.HttpResponse;
0038:        import org.apache.catalina.Lifecycle;
0039:        import org.apache.catalina.LifecycleException;
0040:        import org.apache.catalina.LifecycleListener;
0041:        import org.apache.catalina.Logger;
0042:        import org.apache.catalina.Realm;
0043:        import org.apache.catalina.core.ContainerBase;
0044:        import org.apache.catalina.deploy.LoginConfig;
0045:        import org.apache.catalina.deploy.SecurityConstraint;
0046:        import org.apache.catalina.deploy.SecurityCollection;
0047:        import org.apache.catalina.util.HexUtils;
0048:        import org.apache.catalina.util.LifecycleSupport;
0049:        import org.apache.catalina.util.MD5Encoder;
0050:        import org.apache.catalina.util.StringManager;
0051:        import org.apache.commons.logging.Log;
0052:        import org.apache.commons.logging.LogFactory;
0053:        import org.apache.commons.modeler.Registry;
0054:
0055:        /**
0056:         * Simple implementation of <b>Realm</b> that reads an XML file to configure
0057:         * the valid users, passwords, and roles.  The file format (and default file
0058:         * location) are identical to those currently supported by Tomcat 3.X.
0059:         *
0060:         * @author Craig R. McClanahan
0061:         * @version $Revision: 1.33 $ $Date: 2004/05/26 15:51:25 $
0062:         */
0063:
0064:        public abstract class RealmBase implements  Lifecycle, Realm,
0065:                MBeanRegistration {
0066:
0067:            private static Log log = LogFactory.getLog(RealmBase.class);
0068:
0069:            // ----------------------------------------------------- Instance Variables
0070:
0071:            /**
0072:             * The Container with which this Realm is associated.
0073:             */
0074:            protected Container container = null;
0075:
0076:            /**
0077:             * The debugging detail level for this component.
0078:             */
0079:            protected int debug = 0;
0080:
0081:            /**
0082:             * Digest algorithm used in storing passwords in a non-plaintext format.
0083:             * Valid values are those accepted for the algorithm name by the
0084:             * MessageDigest class, or <code>null</code> if no digesting should
0085:             * be performed.
0086:             */
0087:            protected String digest = null;
0088:
0089:            /**
0090:             * Descriptive information about this Realm implementation.
0091:             */
0092:            protected static final String info = "org.apache.catalina.realm.RealmBase/1.0";
0093:
0094:            /**
0095:             * The lifecycle event support for this component.
0096:             */
0097:            protected LifecycleSupport lifecycle = new LifecycleSupport(this );
0098:
0099:            /**
0100:             * The MessageDigest object for digesting user credentials (passwords).
0101:             */
0102:            protected MessageDigest md = null;
0103:
0104:            /**
0105:             * The MD5 helper object for this class.
0106:             */
0107:            protected static final MD5Encoder md5Encoder = new MD5Encoder();
0108:
0109:            /**
0110:             * MD5 message digest provider.
0111:             */
0112:            protected static MessageDigest md5Helper;
0113:
0114:            /**
0115:             * The string manager for this package.
0116:             */
0117:            protected static StringManager sm = StringManager
0118:                    .getManager(Constants.Package);
0119:
0120:            /**
0121:             * Has this component been started?
0122:             */
0123:            protected boolean started = false;
0124:
0125:            /**
0126:             * The property change support for this component.
0127:             */
0128:            protected PropertyChangeSupport support = new PropertyChangeSupport(
0129:                    this );
0130:
0131:            /**
0132:             * Should we validate client certificate chains when they are presented?
0133:             */
0134:            protected boolean validate = true;
0135:
0136:            // ------------------------------------------------------------- Properties
0137:
0138:            /**
0139:             * Return the Container with which this Realm has been associated.
0140:             */
0141:            public Container getContainer() {
0142:
0143:                return (container);
0144:
0145:            }
0146:
0147:            /**
0148:             * Set the Container with which this Realm has been associated.
0149:             *
0150:             * @param container The associated Container
0151:             */
0152:            public void setContainer(Container container) {
0153:
0154:                Container oldContainer = this .container;
0155:                this .container = container;
0156:                support.firePropertyChange("container", oldContainer,
0157:                        this .container);
0158:
0159:            }
0160:
0161:            /**
0162:             * Return the debugging detail level for this component.
0163:             */
0164:            public int getDebug() {
0165:
0166:                return (this .debug);
0167:
0168:            }
0169:
0170:            /**
0171:             * Set the debugging detail level for this component.
0172:             *
0173:             * @param debug The new debugging detail level
0174:             */
0175:            public void setDebug(int debug) {
0176:
0177:                this .debug = debug;
0178:
0179:            }
0180:
0181:            /**
0182:             * Return the digest algorithm  used for storing credentials.
0183:             */
0184:            public String getDigest() {
0185:
0186:                return digest;
0187:
0188:            }
0189:
0190:            /**
0191:             * Set the digest algorithm used for storing credentials.
0192:             *
0193:             * @param digest The new digest algorithm
0194:             */
0195:            public void setDigest(String digest) {
0196:
0197:                this .digest = digest;
0198:
0199:            }
0200:
0201:            /**
0202:             * Return descriptive information about this Realm implementation and
0203:             * the corresponding version number, in the format
0204:             * <code>&lt;description&gt;/&lt;version&gt;</code>.
0205:             */
0206:            public String getInfo() {
0207:
0208:                return info;
0209:
0210:            }
0211:
0212:            /**
0213:             * Return the "validate certificate chains" flag.
0214:             */
0215:            public boolean getValidate() {
0216:
0217:                return (this .validate);
0218:
0219:            }
0220:
0221:            /**
0222:             * Set the "validate certificate chains" flag.
0223:             *
0224:             * @param validate The new validate certificate chains flag
0225:             */
0226:            public void setValidate(boolean validate) {
0227:
0228:                this .validate = validate;
0229:
0230:            }
0231:
0232:            // --------------------------------------------------------- Public Methods
0233:
0234:            /**
0235:             * Add a property change listener to this component.
0236:             *
0237:             * @param listener The listener to add
0238:             */
0239:            public void addPropertyChangeListener(
0240:                    PropertyChangeListener listener) {
0241:
0242:                support.addPropertyChangeListener(listener);
0243:
0244:            }
0245:
0246:            /**
0247:             * Return the Principal associated with the specified username and
0248:             * credentials, if there is one; otherwise return <code>null</code>.
0249:             *
0250:             * @param username Username of the Principal to look up
0251:             * @param credentials Password or other credentials to use in
0252:             *  authenticating this username
0253:             */
0254:            public Principal authenticate(String username, String credentials) {
0255:
0256:                String serverCredentials = getPassword(username);
0257:
0258:                if ((serverCredentials == null)
0259:                        || (!serverCredentials.equals(credentials)))
0260:                    return null;
0261:
0262:                return getPrincipal(username);
0263:
0264:            }
0265:
0266:            /**
0267:             * Return the Principal associated with the specified username and
0268:             * credentials, if there is one; otherwise return <code>null</code>.
0269:             *
0270:             * @param username Username of the Principal to look up
0271:             * @param credentials Password or other credentials to use in
0272:             *  authenticating this username
0273:             */
0274:            public Principal authenticate(String username, byte[] credentials) {
0275:
0276:                return (authenticate(username, credentials.toString()));
0277:
0278:            }
0279:
0280:            /**
0281:             * Return the Principal associated with the specified username, which
0282:             * matches the digest calculated using the given parameters using the
0283:             * method described in RFC 2069; otherwise return <code>null</code>.
0284:             *
0285:             * @param username Username of the Principal to look up
0286:             * @param clientDigest Digest which has been submitted by the client
0287:             * @param nOnce Unique (or supposedly unique) token which has been used
0288:             * for this request
0289:             * @param realm Realm name
0290:             * @param md5a2 Second MD5 digest used to calculate the digest :
0291:             * MD5(Method + ":" + uri)
0292:             */
0293:            public Principal authenticate(String username, String clientDigest,
0294:                    String nOnce, String nc, String cnonce, String qop,
0295:                    String realm, String md5a2) {
0296:
0297:                /*
0298:                  System.out.println("Digest : " + clientDigest);
0299:
0300:                  System.out.println("************ Digest info");
0301:                  System.out.println("Username:" + username);
0302:                  System.out.println("ClientSigest:" + clientDigest);
0303:                  System.out.println("nOnce:" + nOnce);
0304:                  System.out.println("nc:" + nc);
0305:                  System.out.println("cnonce:" + cnonce);
0306:                  System.out.println("qop:" + qop);
0307:                  System.out.println("realm:" + realm);
0308:                  System.out.println("md5a2:" + md5a2);
0309:                 */
0310:
0311:                String md5a1 = getDigest(username, realm);
0312:                if (md5a1 == null)
0313:                    return null;
0314:                String serverDigestValue = md5a1 + ":" + nOnce + ":" + nc + ":"
0315:                        + cnonce + ":" + qop + ":" + md5a2;
0316:                String serverDigest = md5Encoder.encode(md5Helper
0317:                        .digest(serverDigestValue.getBytes()));
0318:                //System.out.println("Server digest : " + serverDigest);
0319:
0320:                if (serverDigest.equals(clientDigest))
0321:                    return getPrincipal(username);
0322:                else
0323:                    return null;
0324:            }
0325:
0326:            /**
0327:             * Return the Principal associated with the specified chain of X509
0328:             * client certificates.  If there is none, return <code>null</code>.
0329:             *
0330:             * @param certs Array of client certificates, with the first one in
0331:             *  the array being the certificate of the client itself.
0332:             */
0333:            public Principal authenticate(X509Certificate certs[]) {
0334:
0335:                if ((certs == null) || (certs.length < 1))
0336:                    return (null);
0337:
0338:                // Check the validity of each certificate in the chain
0339:                if (log.isDebugEnabled())
0340:                    log.debug("Authenticating client certificate chain");
0341:                if (validate) {
0342:                    for (int i = 0; i < certs.length; i++) {
0343:                        if (log.isDebugEnabled())
0344:                            log.debug(" Checking validity for '"
0345:                                    + certs[i].getSubjectDN().getName() + "'");
0346:                        try {
0347:                            certs[i].checkValidity();
0348:                        } catch (Exception e) {
0349:                            if (log.isDebugEnabled())
0350:                                log.debug("  Validity exception", e);
0351:                            return (null);
0352:                        }
0353:                    }
0354:                }
0355:
0356:                // Check the existence of the client Principal in our database
0357:                return (getPrincipal(certs[0].getSubjectDN().getName()));
0358:
0359:            }
0360:
0361:            /**
0362:             * Return the SecurityConstraints configured to guard the request URI for
0363:             * this request, or <code>null</code> if there is no such constraint.
0364:             *
0365:             * @param request Request we are processing
0366:             * @param context Context the Request is mapped to
0367:             */
0368:            public SecurityConstraint[] findSecurityConstraints(
0369:                    HttpRequest request, Context context) {
0370:
0371:                ArrayList results = null;
0372:                // Are there any defined security constraints?
0373:                SecurityConstraint constraints[] = context.findConstraints();
0374:                if ((constraints == null) || (constraints.length == 0)) {
0375:                    if (log.isDebugEnabled())
0376:                        log.debug("  No applicable constraints defined");
0377:                    return (null);
0378:                }
0379:
0380:                // Check each defined security constraint
0381:                HttpServletRequest hreq = (HttpServletRequest) request
0382:                        .getRequest();
0383:                String uri = request.getRequestPathMB().toString();
0384:
0385:                String method = hreq.getMethod();
0386:                int i;
0387:                boolean found = false;
0388:                for (i = 0; i < constraints.length; i++) {
0389:                    SecurityCollection[] collection = constraints[i]
0390:                            .findCollections();
0391:
0392:                    if (log.isDebugEnabled())
0393:                        log.debug("  Checking constraint '" + constraints[i]
0394:                                + "' against " + method + " " + uri + " --> "
0395:                                + constraints[i].included(uri, method));
0396:                    for (int j = 0; j < collection.length; j++) {
0397:                        String[] patterns = collection[j].findPatterns();
0398:                        for (int k = 0; k < patterns.length; k++) {
0399:                            if (uri.equals(patterns[k])) {
0400:                                found = true;
0401:                                if (collection[j].findMethod(method)) {
0402:                                    if (results == null) {
0403:                                        results = new ArrayList();
0404:                                    }
0405:                                    results.add(constraints[i]);
0406:                                }
0407:                            }
0408:                        }
0409:                    }
0410:                }
0411:
0412:                if (found) {
0413:                    return resultsToArray(results);
0414:                }
0415:
0416:                int longest = -1;
0417:
0418:                for (i = 0; i < constraints.length; i++) {
0419:                    SecurityCollection[] collection = constraints[i]
0420:                            .findCollections();
0421:
0422:                    if (log.isDebugEnabled())
0423:                        log.debug("  Checking constraint '" + constraints[i]
0424:                                + "' against " + method + " " + uri + " --> "
0425:                                + constraints[i].included(uri, method));
0426:                    for (int j = 0; j < collection.length; j++) {
0427:                        String[] patterns = collection[j].findPatterns();
0428:                        boolean matched = false;
0429:                        int length = -1;
0430:                        for (int k = 0; k < patterns.length; k++) {
0431:                            String pattern = patterns[k];
0432:                            if (pattern.startsWith("/")
0433:                                    && pattern.endsWith("/*")
0434:                                    && pattern.length() >= longest) {
0435:
0436:                                if (pattern.length() == 2) {
0437:                                    matched = true;
0438:                                    length = pattern.length();
0439:                                } else if (pattern.regionMatches(0, uri, 0,
0440:                                        pattern.length() - 1)
0441:                                        || (pattern.length() - 2 == uri
0442:                                                .length() && pattern
0443:                                                .regionMatches(0, uri, 0,
0444:                                                        pattern.length() - 2))) {
0445:                                    matched = true;
0446:                                    length = pattern.length();
0447:                                }
0448:                            }
0449:                        }
0450:                        if (matched) {
0451:                            found = true;
0452:                            if (length > longest) {
0453:                                if (results != null) {
0454:                                    results.clear();
0455:                                }
0456:                                longest = length;
0457:                            }
0458:                            if (collection[j].findMethod(method)) {
0459:                                if (results == null) {
0460:                                    results = new ArrayList();
0461:                                }
0462:                                results.add(constraints[i]);
0463:                            }
0464:                        }
0465:                    }
0466:                }
0467:
0468:                if (found) {
0469:                    return resultsToArray(results);
0470:                }
0471:
0472:                for (i = 0; i < constraints.length; i++) {
0473:                    SecurityCollection[] collection = constraints[i]
0474:                            .findCollections();
0475:
0476:                    if (log.isDebugEnabled())
0477:                        log.debug("  Checking constraint '" + constraints[i]
0478:                                + "' against " + method + " " + uri + " --> "
0479:                                + constraints[i].included(uri, method));
0480:                    boolean matched = false;
0481:                    int pos = -1;
0482:                    for (int j = 0; j < collection.length; j++) {
0483:                        String[] patterns = collection[j].findPatterns();
0484:                        for (int k = 0; k < patterns.length && !matched; k++) {
0485:                            String pattern = patterns[k];
0486:                            if (pattern.startsWith("*.")) {
0487:                                int slash = uri.lastIndexOf("/");
0488:                                int dot = uri.lastIndexOf(".");
0489:                                if (slash >= 0
0490:                                        && dot > slash
0491:                                        && dot != uri.length() - 1
0492:                                        && uri.length() - dot == pattern
0493:                                                .length() - 1) {
0494:                                    if (pattern.regionMatches(1, uri, dot, uri
0495:                                            .length()
0496:                                            - dot)) {
0497:                                        matched = true;
0498:                                        pos = j;
0499:                                    }
0500:                                }
0501:                            }
0502:                        }
0503:                    }
0504:                    if (matched) {
0505:                        found = true;
0506:                        if (collection[pos].findMethod(method)) {
0507:                            if (results == null) {
0508:                                results = new ArrayList();
0509:                            }
0510:                            results.add(constraints[i]);
0511:                        }
0512:                    }
0513:                }
0514:
0515:                if (found) {
0516:                    return resultsToArray(results);
0517:                }
0518:
0519:                for (i = 0; i < constraints.length; i++) {
0520:                    SecurityCollection[] collection = constraints[i]
0521:                            .findCollections();
0522:
0523:                    if (log.isDebugEnabled())
0524:                        log.debug("  Checking constraint '" + constraints[i]
0525:                                + "' against " + method + " " + uri + " --> "
0526:                                + constraints[i].included(uri, method));
0527:                    for (int j = 0; j < collection.length; j++) {
0528:                        String[] patterns = collection[j].findPatterns();
0529:                        boolean matched = false;
0530:                        for (int k = 0; k < patterns.length && !matched; k++) {
0531:                            String pattern = patterns[k];
0532:                            if (pattern.equals("/")) {
0533:                                matched = true;
0534:                            }
0535:                        }
0536:                        if (matched) {
0537:                            if (results == null) {
0538:                                results = new ArrayList();
0539:                            }
0540:                            results.add(constraints[i]);
0541:                        }
0542:                    }
0543:                }
0544:
0545:                if (results == null) {
0546:                    // No applicable security constraint was found
0547:                    if (log.isDebugEnabled())
0548:                        log.debug("  No applicable constraint located");
0549:                }
0550:                return resultsToArray(results);
0551:            }
0552:
0553:            /**
0554:             * Convert an ArrayList to a SecurityContraint [].
0555:             */
0556:            private SecurityConstraint[] resultsToArray(ArrayList results) {
0557:                if (results == null) {
0558:                    return null;
0559:                }
0560:                SecurityConstraint[] array = new SecurityConstraint[results
0561:                        .size()];
0562:                results.toArray(array);
0563:                return array;
0564:            }
0565:
0566:            /**
0567:             * Perform access control based on the specified authorization constraint.
0568:             * Return <code>true</code> if this constraint is satisfied and processing
0569:             * should continue, or <code>false</code> otherwise.
0570:             *
0571:             * @param request Request we are processing
0572:             * @param response Response we are creating
0573:             * @param constraints Security constraint we are enforcing
0574:             * @param context The Context to which client of this class is attached.
0575:             *
0576:             * @exception IOException if an input/output error occurs
0577:             */
0578:            public boolean hasResourcePermission(HttpRequest request,
0579:                    HttpResponse response, SecurityConstraint[] constraints,
0580:                    Context context) throws IOException {
0581:
0582:                if (constraints == null || constraints.length == 0)
0583:                    return (true);
0584:
0585:                // Specifically allow access to the form login and form error pages
0586:                // and the "j_security_check" action
0587:                LoginConfig config = context.getLoginConfig();
0588:                if ((config != null)
0589:                        && (Constants.FORM_METHOD
0590:                                .equals(config.getAuthMethod()))) {
0591:                    String requestURI = request.getDecodedRequestURI();
0592:                    String loginPage = context.getPath()
0593:                            + config.getLoginPage();
0594:                    if (loginPage.equals(requestURI)) {
0595:                        if (log.isDebugEnabled())
0596:                            log.debug(" Allow access to login page "
0597:                                    + loginPage);
0598:                        return (true);
0599:                    }
0600:                    String errorPage = context.getPath()
0601:                            + config.getErrorPage();
0602:                    if (errorPage.equals(requestURI)) {
0603:                        if (log.isDebugEnabled())
0604:                            log.debug(" Allow access to error page "
0605:                                    + errorPage);
0606:                        return (true);
0607:                    }
0608:                    if (requestURI.endsWith(Constants.FORM_ACTION)) {
0609:                        if (log.isDebugEnabled())
0610:                            log
0611:                                    .debug(" Allow access to username/password submission");
0612:                        return (true);
0613:                    }
0614:                }
0615:
0616:                // Which user principal have we already authenticated?
0617:                Principal principal = ((HttpServletRequest) request
0618:                        .getRequest()).getUserPrincipal();
0619:                for (int i = 0; i < constraints.length; i++) {
0620:                    SecurityConstraint constraint = constraints[i];
0621:                    String roles[] = constraint.findAuthRoles();
0622:                    if (roles == null)
0623:                        roles = new String[0];
0624:
0625:                    if (constraint.getAllRoles())
0626:                        return (true);
0627:
0628:                    if (log.isDebugEnabled())
0629:                        log.debug("  Checking roles " + principal);
0630:
0631:                    if (roles.length == 0) {
0632:                        if (constraint.getAuthConstraint()) {
0633:                            ((HttpServletResponse) response.getResponse())
0634:                                    .sendError(
0635:                                            HttpServletResponse.SC_FORBIDDEN,
0636:                                            sm.getString("realmBase.forbidden"));
0637:                            if (log.isDebugEnabled())
0638:                                log.debug("No roles ");
0639:                            return (false); // No listed roles means no access at all
0640:                        } else {
0641:                            log.debug("Passing all access");
0642:                            return (true);
0643:                        }
0644:                    } else if (principal == null) {
0645:                        if (log.isDebugEnabled())
0646:                            log
0647:                                    .debug("  No user authenticated, cannot grant access");
0648:                        ((HttpServletResponse) response.getResponse())
0649:                                .sendError(
0650:                                        HttpServletResponse.SC_FORBIDDEN,
0651:                                        sm
0652:                                                .getString("realmBase.notAuthenticated"));
0653:                        return (false);
0654:                    }
0655:
0656:                    for (int j = 0; j < roles.length; j++) {
0657:                        if (hasRole(principal, roles[j]))
0658:                            return (true);
0659:                        if (log.isDebugEnabled())
0660:                            log.debug("No role found:  " + roles[j]);
0661:                    }
0662:                }
0663:                // Return a "Forbidden" message denying access to this resource
0664:                ((HttpServletResponse) response.getResponse()).sendError(
0665:                        HttpServletResponse.SC_FORBIDDEN, sm
0666:                                .getString("realmBase.forbidden"));
0667:                return (false);
0668:
0669:            }
0670:
0671:            /**
0672:             * Return <code>true</code> if the specified Principal has the specified
0673:             * security role, within the context of this Realm; otherwise return
0674:             * <code>false</code>.  This method can be overridden by Realm
0675:             * implementations, but the default is adequate when an instance of
0676:             * <code>GenericPrincipal</code> is used to represent authenticated
0677:             * Principals from this Realm.
0678:             *
0679:             * @param principal Principal for whom the role is to be checked
0680:             * @param role Security role to be checked
0681:             */
0682:            public boolean hasRole(Principal principal, String role) {
0683:
0684:                // Should be overriten in JAASRealm - to avoid pretty inefficient conversions
0685:                if ((principal == null) || (role == null)
0686:                        || !(principal instanceof  GenericPrincipal))
0687:                    return (false);
0688:
0689:                GenericPrincipal gp = (GenericPrincipal) principal;
0690:                if (!(gp.getRealm() == this )) {
0691:                    log.debug("Different realm " + this  + " " + gp.getRealm());//    return (false);
0692:                }
0693:                boolean result = gp.hasRole(role);
0694:                if (log.isDebugEnabled()) {
0695:                    String name = principal.getName();
0696:                    if (result)
0697:                        log.debug(sm.getString("realmBase.hasRoleSuccess",
0698:                                name, role));
0699:                    else
0700:                        log.debug(sm.getString("realmBase.hasRoleFailure",
0701:                                name, role));
0702:                }
0703:                return (result);
0704:
0705:            }
0706:
0707:            /**
0708:             * Enforce any user data constraint required by the security constraint
0709:             * guarding this request URI.  Return <code>true</code> if this constraint
0710:             * was not violated and processing should continue, or <code>false</code>
0711:             * if we have created a response already.
0712:             *
0713:             * @param request Request we are processing
0714:             * @param response Response we are creating
0715:             * @param constraints Security constraint being checked
0716:             *
0717:             * @exception IOException if an input/output error occurs
0718:             */
0719:            public boolean hasUserDataPermission(HttpRequest request,
0720:                    HttpResponse response, SecurityConstraint[] constraints)
0721:                    throws IOException {
0722:
0723:                // Is there a relevant user data constraint?
0724:                if (constraints == null || constraints.length == 0) {
0725:                    if (log.isDebugEnabled())
0726:                        log
0727:                                .debug("  No applicable security constraint defined");
0728:                    return (true);
0729:                }
0730:                for (int i = 0; i < constraints.length; i++) {
0731:                    SecurityConstraint constraint = constraints[i];
0732:                    String userConstraint = constraint.getUserConstraint();
0733:                    if (userConstraint == null) {
0734:                        if (log.isDebugEnabled())
0735:                            log
0736:                                    .debug("  No applicable user data constraint defined");
0737:                        return (true);
0738:                    }
0739:                    if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
0740:                        if (log.isDebugEnabled())
0741:                            log
0742:                                    .debug("  User data constraint has no restrictions");
0743:                        return (true);
0744:                    }
0745:
0746:                }
0747:                // Validate the request against the user data constraint
0748:                if (request.getRequest().isSecure()) {
0749:                    if (log.isDebugEnabled())
0750:                        log.debug("  User data constraint already satisfied");
0751:                    return (true);
0752:                }
0753:                // Initialize variables we need to determine the appropriate action
0754:                HttpServletRequest hrequest = (HttpServletRequest) request
0755:                        .getRequest();
0756:                HttpServletResponse hresponse = (HttpServletResponse) response
0757:                        .getResponse();
0758:                int redirectPort = request.getConnector().getRedirectPort();
0759:
0760:                // Is redirecting disabled?
0761:                if (redirectPort <= 0) {
0762:                    if (log.isDebugEnabled())
0763:                        log.debug("  SSL redirect is disabled");
0764:                    hresponse.sendError(HttpServletResponse.SC_FORBIDDEN,
0765:                            hrequest.getRequestURI());
0766:                    return (false);
0767:                }
0768:
0769:                // Redirect to the corresponding SSL port
0770:                StringBuffer file = new StringBuffer();
0771:                String protocol = "https";
0772:                String host = hrequest.getServerName();
0773:                // Protocol
0774:                file.append(protocol).append("://");
0775:                // Host with port
0776:                file.append(host).append(":").append(redirectPort);
0777:                // URI
0778:                file.append(hrequest.getRequestURI());
0779:                String requestedSessionId = hrequest.getRequestedSessionId();
0780:                if ((requestedSessionId != null)
0781:                        && hrequest.isRequestedSessionIdFromURL()) {
0782:                    file.append(";jsessionid=");
0783:                    file.append(requestedSessionId);
0784:                }
0785:                String queryString = hrequest.getQueryString();
0786:                if (queryString != null) {
0787:                    file.append('?');
0788:                    file.append(queryString);
0789:                }
0790:                if (log.isDebugEnabled())
0791:                    log.debug("  Redirecting to " + file.toString());
0792:                hresponse.sendRedirect(file.toString());
0793:                return (false);
0794:
0795:            }
0796:
0797:            /**
0798:             * Remove a property change listener from this component.
0799:             *
0800:             * @param listener The listener to remove
0801:             */
0802:            public void removePropertyChangeListener(
0803:                    PropertyChangeListener listener) {
0804:
0805:                support.removePropertyChangeListener(listener);
0806:
0807:            }
0808:
0809:            // ------------------------------------------------------ Lifecycle Methods
0810:
0811:            /**
0812:             * Add a lifecycle event listener to this component.
0813:             *
0814:             * @param listener The listener to add
0815:             */
0816:            public void addLifecycleListener(LifecycleListener listener) {
0817:
0818:                lifecycle.addLifecycleListener(listener);
0819:
0820:            }
0821:
0822:            /**
0823:             * Get the lifecycle listeners associated with this lifecycle. If this 
0824:             * Lifecycle has no listeners registered, a zero-length array is returned.
0825:             */
0826:            public LifecycleListener[] findLifecycleListeners() {
0827:
0828:                return lifecycle.findLifecycleListeners();
0829:
0830:            }
0831:
0832:            /**
0833:             * Remove a lifecycle event listener from this component.
0834:             *
0835:             * @param listener The listener to remove
0836:             */
0837:            public void removeLifecycleListener(LifecycleListener listener) {
0838:
0839:                lifecycle.removeLifecycleListener(listener);
0840:
0841:            }
0842:
0843:            /**
0844:             * Prepare for the beginning of active use of the public methods of this
0845:             * component.  This method should be called before any of the public
0846:             * methods of this component are utilized.  It should also send a
0847:             * LifecycleEvent of type START_EVENT to any registered listeners.
0848:             *
0849:             * @exception LifecycleException if this component detects a fatal error
0850:             *  that prevents this component from being used
0851:             */
0852:            public void start() throws LifecycleException {
0853:
0854:                // Validate and update our current component state
0855:                if (started) {
0856:                    log.info(sm.getString("realmBase.alreadyStarted"));
0857:                    return;
0858:                }
0859:                if (!initialized) {
0860:                    init();
0861:                }
0862:                lifecycle.fireLifecycleEvent(START_EVENT, null);
0863:                started = true;
0864:
0865:                // Create a MessageDigest instance for credentials, if desired
0866:                if (digest != null) {
0867:                    try {
0868:                        md = MessageDigest.getInstance(digest);
0869:                    } catch (NoSuchAlgorithmException e) {
0870:                        throw new LifecycleException(sm.getString(
0871:                                "realmBase.algorithm", digest), e);
0872:                    }
0873:                }
0874:
0875:            }
0876:
0877:            /**
0878:             * Gracefully terminate the active use of the public methods of this
0879:             * component.  This method should be the last one called on a given
0880:             * instance of this component.  It should also send a LifecycleEvent
0881:             * of type STOP_EVENT to any registered listeners.
0882:             *
0883:             * @exception LifecycleException if this component detects a fatal error
0884:             *  that needs to be reported
0885:             */
0886:            public void stop() throws LifecycleException {
0887:
0888:                // Validate and update our current component state
0889:                if (!started) {
0890:                    log.info(sm.getString("realmBase.notStarted"));
0891:                    return;
0892:                }
0893:                lifecycle.fireLifecycleEvent(STOP_EVENT, null);
0894:                started = false;
0895:
0896:                // Clean up allocated resources
0897:                md = null;
0898:
0899:                destroy();
0900:
0901:            }
0902:
0903:            public void destroy() {
0904:
0905:                // unregister this realm
0906:                if (oname != null) {
0907:                    try {
0908:                        Registry.getRegistry(null, null).unregisterComponent(
0909:                                oname);
0910:                        log.debug("unregistering realm " + oname);
0911:                    } catch (Exception ex) {
0912:                        log.error("Can't unregister realm " + oname, ex);
0913:                    }
0914:                }
0915:
0916:            }
0917:
0918:            // ------------------------------------------------------ Protected Methods
0919:
0920:            /**
0921:             * Digest the password using the specified algorithm and
0922:             * convert the result to a corresponding hexadecimal string.
0923:             * If exception, the plain credentials string is returned.
0924:             *
0925:             * <strong>IMPLEMENTATION NOTE</strong> - This implementation is
0926:             * synchronized because it reuses the MessageDigest instance.
0927:             * This should be faster than cloning the instance on every request.
0928:             *
0929:             * @param credentials Password or other credentials to use in
0930:             *  authenticating this username
0931:             */
0932:            protected String digest(String credentials) {
0933:
0934:                // If no MessageDigest instance is specified, return unchanged
0935:                if (hasMessageDigest() == false)
0936:                    return (credentials);
0937:
0938:                // Digest the user credentials and return as hexadecimal
0939:                synchronized (this ) {
0940:                    try {
0941:                        md.reset();
0942:                        md.update(credentials.getBytes());
0943:                        return (HexUtils.convert(md.digest()));
0944:                    } catch (Exception e) {
0945:                        log.error(sm.getString("realmBase.digest"), e);
0946:                        return (credentials);
0947:                    }
0948:                }
0949:
0950:            }
0951:
0952:            protected boolean hasMessageDigest() {
0953:                return !(md == null);
0954:            }
0955:
0956:            /**
0957:             * Return the digest associated with given principal's user name.
0958:             */
0959:            protected String getDigest(String username, String realmName) {
0960:                if (md5Helper == null) {
0961:                    try {
0962:                        md5Helper = MessageDigest.getInstance("MD5");
0963:                    } catch (NoSuchAlgorithmException e) {
0964:                        e.printStackTrace();
0965:                        throw new IllegalStateException();
0966:                    }
0967:                }
0968:                String digestValue = username + ":" + realmName + ":"
0969:                        + getPassword(username);
0970:                byte[] digest = md5Helper.digest(digestValue.getBytes());
0971:                return md5Encoder.encode(digest);
0972:            }
0973:
0974:            /**
0975:             * Return a short name for this Realm implementation, for use in
0976:             * log messages.
0977:             */
0978:            protected abstract String getName();
0979:
0980:            /**
0981:             * Return the password associated with the given principal's user name.
0982:             */
0983:            protected abstract String getPassword(String username);
0984:
0985:            /**
0986:             * Return the Principal associated with the given user name.
0987:             */
0988:            protected abstract Principal getPrincipal(String username);
0989:
0990:            /**
0991:             * Log a message on the Logger associated with our Container (if any)
0992:             *
0993:             * @param message Message to be logged
0994:             */
0995:            protected void log(String message) {
0996:
0997:                Logger logger = null;
0998:                String name = null;
0999:                if (container != null) {
1000:                    logger = container.getLogger();
1001:                    name = container.getName();
1002:                }
1003:
1004:                if (logger != null) {
1005:                    logger.log(getName() + "[" + name + "]: " + message);
1006:                } else {
1007:                    System.out
1008:                            .println(getName() + "[" + name + "]: " + message);
1009:                }
1010:
1011:            }
1012:
1013:            /**
1014:             * Log a message on the Logger associated with our Container (if any)
1015:             *
1016:             * @param message Message to be logged
1017:             * @param throwable Associated exception
1018:             */
1019:            protected void log(String message, Throwable throwable) {
1020:
1021:                Logger logger = null;
1022:                String name = null;
1023:                if (container != null) {
1024:                    logger = container.getLogger();
1025:                    name = container.getName();
1026:                }
1027:
1028:                if (logger != null) {
1029:                    logger.log(getName() + "[" + name + "]: " + message,
1030:                            throwable);
1031:                } else {
1032:                    System.out
1033:                            .println(getName() + "[" + name + "]: " + message);
1034:                    throwable.printStackTrace(System.out);
1035:                }
1036:            }
1037:
1038:            // --------------------------------------------------------- Static Methods
1039:
1040:            /**
1041:             * Digest password using the algorithm especificied and
1042:             * convert the result to a corresponding hex string.
1043:             * If exception, the plain credentials string is returned
1044:             *
1045:             * @param credentials Password or other credentials to use in
1046:             *  authenticating this username
1047:             * @param algorithm Algorithm used to do th digest
1048:             */
1049:            public final static String Digest(String credentials,
1050:                    String algorithm) {
1051:
1052:                try {
1053:                    // Obtain a new message digest with "digest" encryption
1054:                    MessageDigest md = (MessageDigest) MessageDigest
1055:                            .getInstance(algorithm).clone();
1056:                    // encode the credentials
1057:                    md.update(credentials.getBytes());
1058:                    // Digest the credentials and return as hexadecimal
1059:                    return (HexUtils.convert(md.digest()));
1060:                } catch (Exception ex) {
1061:                    ex.printStackTrace();
1062:                    return credentials;
1063:                }
1064:
1065:            }
1066:
1067:            /**
1068:             * Digest password using the algorithm especificied and
1069:             * convert the result to a corresponding hex string.
1070:             * If exception, the plain credentials string is returned
1071:             */
1072:            public static void main(String args[]) {
1073:
1074:                if (args.length > 2 && args[0].equalsIgnoreCase("-a")) {
1075:                    for (int i = 2; i < args.length; i++) {
1076:                        System.out.print(args[i] + ":");
1077:                        System.out.println(Digest(args[i], args[1]));
1078:                    }
1079:                } else {
1080:                    System.out
1081:                            .println("Usage: RealmBase -a <algorithm> <credentials>");
1082:                }
1083:
1084:            }
1085:
1086:            // -------------------- JMX and Registration  --------------------
1087:            protected String type;
1088:            protected String domain;
1089:            protected String host;
1090:            protected String path;
1091:            protected ObjectName oname;
1092:            protected ObjectName controller;
1093:            protected MBeanServer mserver;
1094:
1095:            public ObjectName getController() {
1096:                return controller;
1097:            }
1098:
1099:            public void setController(ObjectName controller) {
1100:                this .controller = controller;
1101:            }
1102:
1103:            public ObjectName getObjectName() {
1104:                return oname;
1105:            }
1106:
1107:            public String getDomain() {
1108:                return domain;
1109:            }
1110:
1111:            public String getType() {
1112:                return type;
1113:            }
1114:
1115:            public ObjectName preRegister(MBeanServer server, ObjectName name)
1116:                    throws Exception {
1117:                oname = name;
1118:                mserver = server;
1119:                domain = name.getDomain();
1120:
1121:                type = name.getKeyProperty("type");
1122:                host = name.getKeyProperty("host");
1123:                path = name.getKeyProperty("path");
1124:
1125:                return name;
1126:            }
1127:
1128:            public void postRegister(Boolean registrationDone) {
1129:            }
1130:
1131:            public void preDeregister() throws Exception {
1132:            }
1133:
1134:            public void postDeregister() {
1135:            }
1136:
1137:            protected boolean initialized = false;
1138:
1139:            public void init() {
1140:                if (initialized && container != null)
1141:                    return;
1142:
1143:                initialized = true;
1144:                if (container == null) {
1145:                    ObjectName parent = null;
1146:                    // Register with the parent
1147:                    try {
1148:                        if (host == null) {
1149:                            // global
1150:                            parent = new ObjectName(domain + ":type=Engine");
1151:                        } else if (path == null) {
1152:                            parent = new ObjectName(domain + ":type=Host,host="
1153:                                    + host);
1154:                        } else {
1155:                            parent = new ObjectName(domain
1156:                                    + ":j2eeType=WebModule,name=//" + host
1157:                                    + path);
1158:                        }
1159:                        if (mserver.isRegistered(parent)) {
1160:                            log.debug("Register with " + parent);
1161:                            mserver
1162:                                    .invoke(
1163:                                            parent,
1164:                                            "setRealm",
1165:                                            new Object[] { this  },
1166:                                            new String[] { "org.apache.catalina.Realm" });
1167:                        }
1168:                    } catch (Exception e) {
1169:                        log.info("Parent not available yet: " + parent);
1170:                    }
1171:                }
1172:
1173:                if (oname == null) {
1174:                    // register
1175:                    try {
1176:                        ContainerBase cb = (ContainerBase) container;
1177:                        oname = new ObjectName(cb.getDomain() + ":type=Realm"
1178:                                + cb.getContainerSuffix());
1179:                        Registry.getRegistry(null, null).registerComponent(
1180:                                this , oname, null);
1181:                        log.debug("Register Realm " + oname);
1182:                    } catch (Throwable e) {
1183:                        log.error("Can't register " + oname, e);
1184:                    }
1185:                }
1186:
1187:            }
1188:
1189:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.