Source Code Cross Referenced for SecurityVerifier.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » auth » 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 » Wiki Engine » JSPWiki » com.ecyrd.jspwiki.auth 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         JSPWiki - a JSP-based WikiWiki clone.
003:
004:         Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006:         This program is free software; you can redistribute it and/or modify
007:         it under the terms of the GNU Lesser General Public License as published by
008:         the Free Software Foundation; either version 2.1 of the License, or
009:         (at your option) any later version.
010:
011:         This program is distributed in the hope that it will be useful,
012:         but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:         GNU Lesser General Public License for more details.
015:
016:         You should have received a copy of the GNU Lesser General Public License
017:         along with this program; if not, write to the Free Software
018:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         */
020:        package com.ecyrd.jspwiki.auth;
021:
022:        import java.io.File;
023:        import java.io.IOException;
024:        import java.net.MalformedURLException;
025:        import java.net.URL;
026:        import java.security.*;
027:        import java.util.Iterator;
028:        import java.util.LinkedHashSet;
029:        import java.util.List;
030:        import java.util.Set;
031:
032:        import javax.security.auth.Subject;
033:        import javax.security.auth.login.LoginContext;
034:
035:        import org.apache.commons.lang.ArrayUtils;
036:        import org.apache.log4j.Logger;
037:        import org.freshcookies.security.policy.PolicyReader;
038:        import org.jdom.JDOMException;
039:
040:        import com.ecyrd.jspwiki.InternalWikiException;
041:        import com.ecyrd.jspwiki.WikiEngine;
042:        import com.ecyrd.jspwiki.WikiException;
043:        import com.ecyrd.jspwiki.WikiSession;
044:        import com.ecyrd.jspwiki.auth.authorize.*;
045:        import com.ecyrd.jspwiki.auth.permissions.AllPermission;
046:        import com.ecyrd.jspwiki.auth.permissions.GroupPermission;
047:        import com.ecyrd.jspwiki.auth.permissions.PermissionFactory;
048:        import com.ecyrd.jspwiki.auth.permissions.WikiPermission;
049:        import com.ecyrd.jspwiki.auth.user.DefaultUserProfile;
050:        import com.ecyrd.jspwiki.auth.user.UserDatabase;
051:        import com.ecyrd.jspwiki.auth.user.UserProfile;
052:
053:        /**
054:         * Helper class for verifying JSPWiki's security configuration. Invoked by
055:         * <code>admin/SecurityConfig.jsp</code>.
056:         * @author Andrew Jaquith
057:         * @since 2.4
058:         */
059:        public final class SecurityVerifier {
060:            private static final long serialVersionUID = -3859563355089169941L;
061:
062:            private WikiEngine m_engine;
063:
064:            private File m_jaasConfig = null;
065:
066:            private boolean m_isJaasConfigured = false;
067:
068:            private boolean m_isSecurityPolicyConfigured = false;
069:
070:            private Principal[] m_policyPrincipals = new Principal[0];
071:
072:            private WikiSession m_session;
073:
074:            /** Message prefix for errors. */
075:            public static final String ERROR = "Error.";
076:
077:            /** Message prefix for warnings. */
078:            public static final String WARNING = "Warning.";
079:
080:            /** Message prefix for information messages. */
081:            public static final String INFO = "Info.";
082:
083:            /** Message topic for policy errors. */
084:            public static final String ERROR_POLICY = "Error.Policy";
085:
086:            /** Message topic for policy warnings. */
087:            public static final String WARNING_POLICY = "Warning.Policy";
088:
089:            /** Message topic for policy information messages. */
090:            public static final String INFO_POLICY = "Info.Policy";
091:
092:            /** Message topic for JAAS errors. */
093:            public static final String ERROR_JAAS = "Error.Jaas";
094:
095:            /** Message topic for JAAS warnings. */
096:            public static final String WARNING_JAAS = "Warning.Jaas";
097:
098:            /** Message topic for role-checking errors. */
099:            public static final String ERROR_ROLES = "Error.Roles";
100:
101:            /** Message topic for role-checking information messages. */
102:            public static final String INFO_ROLES = "Info.Roles";
103:
104:            /** Message topic for user database errors. */
105:            public static final String ERROR_DB = "Error.UserDatabase";
106:
107:            /** Message topic for user database warnings. */
108:            public static final String WARNING_DB = "Warning.UserDatabase";
109:
110:            /** Message topic for user database information messages. */
111:            public static final String INFO_DB = "Info.UserDatabase";
112:
113:            /** Message topic for group database errors. */
114:            public static final String ERROR_GROUPS = "Error.GroupDatabase";
115:
116:            /** Message topic for group database warnings. */
117:            public static final String WARNING_GROUPS = "Warning.GroupDatabase";
118:
119:            /** Message topic for group database information messages. */
120:            public static final String INFO_GROUPS = "Info.GroupDatabase";
121:
122:            /** Message topic for JAAS information messages. */
123:            public static final String INFO_JAAS = "Info.Jaas";
124:
125:            private static final String[] CONTAINER_ACTIONS = new String[] {
126:                    "View pages", "Comment on existing pages", "Edit pages",
127:                    "Upload attachments", "Create a new group",
128:                    "Rename an existing page", "Delete pages" };
129:
130:            private static final String[] CONTAINER_JSPS = new String[] {
131:                    "/Wiki.jsp", "/Comment.jsp", "/Edit.jsp", "/Upload.jsp",
132:                    "/NewGroup.jsp", "/Rename.jsp", "/Delete.jsp" };
133:
134:            private static final String BG_GREEN = "bgcolor=\"#c0ffc0\"";
135:
136:            private static final String BG_RED = "bgcolor=\"#ffc0c0\"";
137:
138:            private static final Logger LOG = Logger
139:                    .getLogger(SecurityVerifier.class.getName());
140:
141:            /**
142:             * Constructs a new SecurityVerifier for a supplied WikiEngine and WikiSession.
143:             * @param engine the wiki engine
144:             * @param session the wiki session (typically, that of an administrator)
145:             */
146:            public SecurityVerifier(WikiEngine engine, WikiSession session) {
147:                super ();
148:                m_engine = engine;
149:                m_session = session;
150:                m_session.clearMessages();
151:                verifyJaas();
152:                verifyPolicy();
153:                try {
154:                    verifyPolicyAndContainerRoles();
155:                } catch (WikiException e) {
156:                    m_session.addMessage(ERROR_ROLES, e.getMessage());
157:                }
158:                verifyGroupDatabase();
159:                verifyUserDatabase();
160:            }
161:
162:            /**
163:             * Returns an array of unique Principals from the JSPWIki security policy
164:             * file. This array will be zero-length if the policy file was not
165:             * successfully located, or if the file did not specify any Principals in
166:             * the policy.
167:             * @return the array of principals
168:             */
169:            public final Principal[] policyPrincipals() {
170:                return m_policyPrincipals;
171:            }
172:
173:            /**
174:             * Formats and returns an HTML table containing sample permissions and what
175:             * roles are allowed to have them. This method will throw an
176:             * {@link IllegalStateException} if the authorizer is not of type
177:             * {@link com.ecyrd.jspwiki.auth.authorize.WebContainerAuthorizer}
178:             * @return the formatted HTML table containing the result of the tests
179:             */
180:            public final String policyRoleTable() {
181:                Principal[] roles = m_policyPrincipals;
182:                String wiki = m_engine.getApplicationName();
183:
184:                String[] pages = new String[] { "Main", "Index", "GroupTest",
185:                        "GroupAdmin" };
186:                String[] pageActions = new String[] { "view", "edit", "modify",
187:                        "rename", "delete" };
188:
189:                String[] groups = new String[] { "Admin", "TestGroup", "Foo" };
190:                String[] groupActions = new String[] { "view", "edit", null,
191:                        null, "delete" };
192:
193:                // Calculate column widths
194:                String colWidth;
195:                if (pageActions.length > 0 && roles.length > 0) {
196:                    colWidth = String
197:                            .valueOf(67f / (pageActions.length * roles.length))
198:                            + "%";
199:                } else {
200:                    colWidth = "67%";
201:                }
202:
203:                StringBuffer s = new StringBuffer();
204:
205:                // Write the table header
206:                s.append("<table class=\"wikitable\" border=\"1\">\n");
207:                s.append("  <colgroup span=\"1\" width=\"33%\"/>\n");
208:                s.append("  <colgroup span=\"" + pageActions.length
209:                        * roles.length + "\" width=\"" + colWidth
210:                        + "\" align=\"center\"/>\n");
211:                s.append("  <tr>\n");
212:                s
213:                        .append("    <th rowspan=\"2\" valign=\"bottom\">Permission</th>\n");
214:                for (int i = 0; i < roles.length; i++) {
215:                    s.append("    <th colspan=\"" + pageActions.length
216:                            + "\" title=\"" + roles[i].getClass().getName()
217:                            + "\">" + roles[i].getName() + "</th>\n");
218:                }
219:                s.append("  </tr>\n");
220:
221:                // Print a column for each role
222:                s.append("  <tr>\n");
223:                for (int i = 0; i < roles.length; i++) {
224:                    for (int j = 0; j < pageActions.length; j++) {
225:                        String action = pageActions[j].substring(0, 1);
226:                        s.append("    <th title=\"" + pageActions[j] + "\">"
227:                                + action + "</th>\n");
228:                    }
229:                }
230:                s.append("  </tr>\n");
231:
232:                // Write page permission tests first
233:                for (int i = 0; i < pages.length; i++) {
234:                    String page = pages[i];
235:                    s.append("  <tr>\n");
236:                    s.append("    <td>PagePermission \"" + wiki + ":" + page
237:                            + "\"</td>\n");
238:                    for (int j = 0; j < roles.length; j++) {
239:                        for (int k = 0; k < pageActions.length; k++) {
240:                            Permission permission = PermissionFactory
241:                                    .getPagePermission(wiki + ":" + page,
242:                                            pageActions[k]);
243:                            s.append(printPermissionTest(permission, roles[j],
244:                                    1));
245:                        }
246:                    }
247:                    s.append("  </tr>\n");
248:                }
249:
250:                // Now do the group tests
251:                for (int i = 0; i < groups.length; i++) {
252:                    String group = groups[i];
253:                    s.append("  <tr>\n");
254:                    s.append("    <td>GroupPermission \"" + wiki + ":" + group
255:                            + "\"</td>\n");
256:                    for (int j = 0; j < roles.length; j++) {
257:                        for (int k = 0; k < groupActions.length; k++) {
258:                            Permission permission = null;
259:                            if (groupActions[k] != null) {
260:                                permission = new GroupPermission(wiki + ":"
261:                                        + group, groupActions[k]);
262:                            }
263:                            s.append(printPermissionTest(permission, roles[j],
264:                                    1));
265:                        }
266:                    }
267:                    s.append("  </tr>\n");
268:                }
269:
270:                // Now check the wiki-wide permissions
271:                String[] wikiPerms = new String[] { "createGroups",
272:                        "createPages", "login", "editPreferences",
273:                        "editProfile" };
274:                for (int i = 0; i < wikiPerms.length; i++) {
275:                    s.append("  <tr>\n");
276:                    s.append("    <td>WikiPermission \"" + wiki + "\",\""
277:                            + wikiPerms[i] + "\"</td>\n");
278:                    for (int j = 0; j < roles.length; j++) {
279:                        Permission permission = new WikiPermission(wiki,
280:                                wikiPerms[i]);
281:                        s.append(printPermissionTest(permission, roles[j],
282:                                pageActions.length));
283:                    }
284:                    s.append("  </tr>\n");
285:                }
286:
287:                // Lastly, check for AllPermission
288:                s.append("  <tr>\n");
289:                s.append("    <td>AllPermission \"" + wiki + "\"</td>\n");
290:                for (int j = 0; j < roles.length; j++) {
291:                    Permission permission = new AllPermission(wiki);
292:                    s.append(printPermissionTest(permission, roles[j],
293:                            pageActions.length));
294:                }
295:                s.append("  </tr>\n");
296:
297:                // We're done!
298:                s.append("</table>");
299:                return s.toString();
300:            }
301:
302:            /**
303:             * Prints a &lt;td&gt; HTML element with the results of a permission test.
304:             * @param perm the permission to format
305:             * @param allowed whether the permission is allowed
306:             */
307:            private final String printPermissionTest(Permission permission,
308:                    Principal principal, int cols) {
309:                StringBuffer s = new StringBuffer();
310:                if (permission == null) {
311:                    s.append("    <td colspan=\"" + cols
312:                            + "\" align=\"center\" title=\"N/A\">");
313:                    s.append("&nbsp;</td>\n");
314:                } else {
315:                    boolean allowed = verifyStaticPermission(principal,
316:                            permission);
317:                    s.append("    <td colspan=\"" + cols
318:                            + "\" align=\"center\" title=\"");
319:                    s.append(allowed ? "ALLOW: " : "DENY: ");
320:                    s.append(permission.getClass().getName());
321:                    s.append(" &quot;");
322:                    s.append(permission.getName());
323:                    s.append("&quot;");
324:                    if (permission.getName() != null) {
325:                        s.append(",&quot;");
326:                        s.append(permission.getActions());
327:                        s.append("&quot;");
328:                    }
329:                    s.append(" ");
330:                    s.append(principal.getClass().getName());
331:                    s.append(" &quot;");
332:                    s.append(principal.getName());
333:                    s.append("&quot;");
334:                    s.append("\"");
335:                    s.append(allowed ? BG_GREEN + ">" : BG_RED + ">");
336:                    s.append("&nbsp;</td>\n");
337:                }
338:                return s.toString();
339:            }
340:
341:            /**
342:             * Formats and returns an HTML table containing the roles the web container
343:             * is aware of, and whether each role maps to particular JSPs. This method
344:             * throws an {@link IllegalStateException} if the authorizer is not of type
345:             * {@link com.ecyrd.jspwiki.auth.authorize.WebContainerAuthorizer}
346:             * @return the formatted HTML table containing the result of the tests
347:             * @throws WikiException if tests fail for unexpected reasons
348:             */
349:            public final String containerRoleTable() throws WikiException {
350:
351:                AuthorizationManager authorizationManager = m_engine
352:                        .getAuthorizationManager();
353:                Authorizer authorizer = authorizationManager.getAuthorizer();
354:
355:                // If authorizer not WebContainerAuthorizer, print error message
356:                if (!(authorizer instanceof  WebContainerAuthorizer)) {
357:                    throw new IllegalStateException(
358:                            "Authorizer should be WebContainerAuthorizer");
359:                }
360:
361:                // Now, print a table with JSP pages listed on the left, and
362:                // an evaluation of each pages' constraints for each role
363:                // we discovered
364:                StringBuffer s = new StringBuffer();
365:                Principal[] roles = authorizer.getRoles();
366:                s.append("<table class=\"wikitable\" border=\"1\">\n");
367:                s.append("<thead>\n");
368:                s.append("  <tr>\n");
369:                s.append("    <th rowspan=\"2\">Action</th>\n");
370:                s.append("    <th rowspan=\"2\">Page</th>\n");
371:                s.append("    <th colspan=\"" + roles.length + 1
372:                        + "\">Roles</th>\n");
373:                s.append("  </tr>\n");
374:                s.append("  <tr>\n");
375:                s.append("    <th>Anonymous</th>\n");
376:                for (int i = 0; i < roles.length; i++) {
377:                    s.append("    <th>" + roles[i].getName() + "</th>\n");
378:                }
379:                s.append("</tr>\n");
380:                s.append("</thead>\n");
381:                s.append("<tbody>\n");
382:
383:                try {
384:                    WebContainerAuthorizer wca = (WebContainerAuthorizer) authorizer;
385:                    for (int i = 0; i < CONTAINER_ACTIONS.length; i++) {
386:                        String action = CONTAINER_ACTIONS[i];
387:                        String jsp = CONTAINER_JSPS[i];
388:
389:                        // Print whether the page is constrained for each role
390:                        boolean allowsAnonymous = !wca.isConstrained(jsp,
391:                                Role.ALL);
392:                        s.append("  <tr>\n");
393:                        s.append("    <td>" + action + "</td>\n");
394:                        s.append("    <td>" + jsp + "</td>\n");
395:                        s.append("    <td title=\"");
396:                        s.append(allowsAnonymous ? "ALLOW: " : "DENY: ");
397:                        s.append(jsp);
398:                        s.append(" Anonymous");
399:                        s.append("\"");
400:                        s.append(allowsAnonymous ? BG_GREEN + ">" : BG_RED
401:                                + ">");
402:                        s.append("&nbsp;</td>\n");
403:                        for (int j = 0; j < roles.length; j++) {
404:                            Role role = (Role) roles[j];
405:                            boolean allowed = allowsAnonymous
406:                                    || wca.isConstrained(jsp, role);
407:                            s.append("    <td title=\"");
408:                            s.append(allowed ? "ALLOW: " : "DENY: ");
409:                            s.append(jsp);
410:                            s.append(" ");
411:                            s.append(role.getClass().getName());
412:                            s.append(" &quot;");
413:                            s.append(role.getName());
414:                            s.append("&quot;");
415:                            s.append("\"");
416:                            s.append(allowed ? BG_GREEN + ">" : BG_RED + ">");
417:                            s.append("&nbsp;</td>\n");
418:                        }
419:                        s.append("  </tr>\n");
420:                    }
421:                } catch (JDOMException e) {
422:                    // If we couldn't evaluate constraints it means
423:                    // there's some sort of IO mess or parsing issue
424:                    LOG.error("Malformed XML in web.xml", e);
425:                    throw new InternalWikiException(e.getClass().getName()
426:                            + ": " + e.getMessage());
427:                }
428:
429:                s.append("</tbody>\n");
430:                s.append("</table>\n");
431:                return s.toString();
432:            }
433:
434:            /**
435:             * Returns <code>true</code> if JAAS is configured correctly.
436:             * @return the result of the configuration check
437:             */
438:            public final boolean isJaasConfigured() {
439:                return m_isJaasConfigured;
440:            }
441:
442:            /**
443:             * Returns <code>true</code> if the JAAS login configuration was already
444:             * set when JSPWiki started up. We determine this value by consulting a
445:             * protected member field of {@link AuthenticationManager}, which was set
446:             * at in initialization by {@link PolicyLoader}.
447:             * @return <code>true</code> if {@link PolicyLoader} successfully set the
448:             *         policy, or <code>false</code> for any other reason.
449:             */
450:            public final boolean isJaasConfiguredAtStartup() {
451:                return m_engine.getAuthenticationManager().m_isJaasConfiguredAtStartup;
452:            }
453:
454:            /**
455:             * Returns <code>true</code> if JSPWiki can locate a named JAAS login
456:             * configuration.
457:             * @param config the name of the application (e.g.,
458:             *            <code>JSPWiki-container</code>).
459:             * @return <code>true</code> if found; <code>false</code> otherwise
460:             */
461:            protected final boolean isJaasConfigurationAvailable(String config) {
462:                try {
463:                    m_session.addMessage(INFO_JAAS, "We found the '" + config
464:                            + "' login configuration.");
465:                    new LoginContext(config);
466:                    return true;
467:                } catch (Exception e) {
468:                    m_session.addMessage(ERROR_JAAS, "We could not find the '"
469:                            + config + "' login configuration.</p>");
470:                    return false;
471:                }
472:            }
473:
474:            /**
475:             * Returns <code>true</code> if the Java security policy is configured
476:             * correctly, and it verifies as valid.
477:             * @return the result of the configuration check
478:             */
479:            public final boolean isSecurityPolicyConfigured() {
480:                return m_isSecurityPolicyConfigured;
481:            }
482:
483:            /**
484:             * If the active Authorizer is the WebContainerAuthorizer, returns the roles
485:             * it knows about; otherwise, a zero-length array.
486:             * @return the roles parsed from <code>web.xml</code>, or a zero-length array
487:             * @throws WikiException if the web authorizer cannot obtain the list of roles
488:             */
489:            public final Principal[] webContainerRoles() throws WikiException {
490:                Authorizer authorizer = m_engine.getAuthorizationManager()
491:                        .getAuthorizer();
492:                if (authorizer instanceof  WebContainerAuthorizer) {
493:                    return ((WebContainerAuthorizer) authorizer).getRoles();
494:                }
495:                return new Principal[0];
496:            }
497:
498:            /**
499:             * Verifies that the roles given in the security policy are reflected by the
500:             * container <code>web.xml</code> file.
501:             * @throws WikiException if the web authorizer cannot verify the roles
502:             */
503:            protected final void verifyPolicyAndContainerRoles()
504:                    throws WikiException {
505:                Authorizer authorizer = m_engine.getAuthorizationManager()
506:                        .getAuthorizer();
507:                Principal[] containerRoles = authorizer.getRoles();
508:                boolean missing = false;
509:                for (int i = 0; i < m_policyPrincipals.length; i++) {
510:                    Principal principal = m_policyPrincipals[i];
511:                    if (principal instanceof  Role) {
512:                        Role role = (Role) principal;
513:                        boolean isContainerRole = ArrayUtils.contains(
514:                                containerRoles, role);
515:                        if (!Role.isBuiltInRole(role) && !isContainerRole) {
516:                            m_session
517:                                    .addMessage(
518:                                            ERROR_ROLES,
519:                                            "Role '"
520:                                                    + role.getName()
521:                                                    + "' is defined in security policy but not in web.xml.");
522:                            missing = true;
523:                        }
524:                    }
525:                }
526:                if (!missing) {
527:                    m_session
528:                            .addMessage(
529:                                    INFO_ROLES,
530:                                    "Every non-standard role defined in the security policy was also found in web.xml.");
531:                }
532:            }
533:
534:            /**
535:             * Verifies that the group datbase was initialized properly, and that
536:             * user add and delete operations work as they should.
537:             */
538:            protected final void verifyGroupDatabase() {
539:                GroupManager mgr = m_engine.getGroupManager();
540:                GroupDatabase db = null;
541:                try {
542:                    db = m_engine.getGroupManager().getGroupDatabase();
543:                } catch (WikiSecurityException e) {
544:                    m_session.addMessage(ERROR_GROUPS,
545:                            "Could not retrieve GroupManager: "
546:                                    + e.getMessage());
547:                }
548:
549:                // Check for obvious error conditions
550:                if (mgr == null || db == null) {
551:                    if (mgr == null) {
552:                        m_session
553:                                .addMessage(
554:                                        ERROR_GROUPS,
555:                                        "GroupManager is null; JSPWiki could not "
556:                                                + "initialize it. Check the error logs.");
557:                    }
558:                    if (db == null) {
559:                        m_session
560:                                .addMessage(
561:                                        ERROR_GROUPS,
562:                                        "GroupDatabase is null; JSPWiki could not "
563:                                                + "initialize it. Check the error logs.");
564:                    }
565:                    return;
566:                }
567:
568:                // Everything initialized OK...
569:
570:                // Tell user what class of database this is.
571:                m_session.addMessage(INFO_GROUPS, "GroupDatabase is of type '"
572:                        + db.getClass().getName()
573:                        + "'. It appears to be initialized properly.");
574:
575:                // Now, see how many groups we have.
576:                int oldGroupCount = 0;
577:                try {
578:                    Group[] groups = db.groups();
579:                    oldGroupCount = groups.length;
580:                    m_session.addMessage(INFO_GROUPS,
581:                            "The group database contains " + oldGroupCount
582:                                    + " groups.");
583:                } catch (WikiSecurityException e) {
584:                    m_session.addMessage(ERROR_GROUPS,
585:                            "Could not obtain a list of current groups: "
586:                                    + e.getMessage());
587:                    return;
588:                }
589:
590:                // Try adding a bogus group with random name
591:                String name = "TestGroup"
592:                        + String.valueOf(System.currentTimeMillis());
593:                Group group = null;
594:                try {
595:                    // Create dummy test group
596:                    group = mgr.parseGroup(name, "", true);
597:                    Principal user = new WikiPrincipal("TestUser");
598:                    group.add(user);
599:                    db.save(group, new WikiPrincipal("SecurityVerifier"));
600:
601:                    // Make sure the group saved successfully
602:                    if (db.groups().length == oldGroupCount) {
603:                        m_session.addMessage(ERROR_GROUPS,
604:                                "Could not add a test group to the database.");
605:                        return;
606:                    }
607:                    m_session
608:                            .addMessage(INFO_GROUPS,
609:                                    "The group database allows new groups to be created, as it should.");
610:                } catch (WikiSecurityException e) {
611:                    m_session.addMessage(ERROR_GROUPS,
612:                            "Could not add a group to the database: "
613:                                    + e.getMessage());
614:                    return;
615:                }
616:
617:                // Now delete the group; should be back to old count
618:                try {
619:                    db.delete(group);
620:                    if (db.groups().length != oldGroupCount) {
621:                        m_session
622:                                .addMessage(ERROR_GROUPS,
623:                                        "Could not delete a test group from the database.");
624:                        return;
625:                    }
626:                    m_session
627:                            .addMessage(INFO_GROUPS,
628:                                    "The group database allows groups to be deleted, as it should.");
629:                } catch (WikiSecurityException e) {
630:                    m_session.addMessage(ERROR_GROUPS,
631:                            "Could not delete a test group from the database: "
632:                                    + e.getMessage());
633:                    return;
634:                }
635:
636:                m_session.addMessage(INFO_GROUPS,
637:                        "The group database configuration looks fine.");
638:            }
639:
640:            /**
641:             * Verfies the JAAS configuration. The configuration is valid if value of
642:             * the system property <code>java.security.auth.login.config</code>
643:             * resolves to an existing file, and we can find the JAAS login
644:             * configurations for <code>JSPWiki-container</code> and
645:             * <code>JSPWiki-custom</code>.
646:             */
647:            protected final void verifyJaas() {
648:                // See if JAAS is on
649:                AuthorizationManager authMgr = m_engine
650:                        .getAuthorizationManager();
651:                if (!authMgr.isJAASAuthorized()) {
652:                    m_session
653:                            .addMessage(
654:                                    ERROR_JAAS,
655:                                    "JSPWiki's JAAS-based authentication "
656:                                            + "and authorization system is turned off (your <code>jspwiki.properties</code> "
657:                                            + "contains the setting 'jspwiki.security = container'. This "
658:                                            + "setting disables authorization checks and is meant for testing "
659:                                            + "and troubleshooting only. The test results on this page will not "
660:                                            + "be reliable as a result. You should set this to 'jaas' "
661:                                            + "so that security works properly.");
662:                }
663:
664:                // Validate the property is set correctly
665:                m_jaasConfig = getFileFromProperty("java.security.auth.login.config");
666:
667:                // Look for the JSPWiki-container config
668:                boolean foundJaasContainerConfig = isJaasConfigurationAvailable("JSPWiki-container");
669:
670:                // Look for the JSPWiki-custom config
671:                boolean foundJaasCustomConfig = isJaasConfigurationAvailable("JSPWiki-custom");
672:
673:                m_isJaasConfigured = m_jaasConfig != null
674:                        && foundJaasContainerConfig && foundJaasCustomConfig;
675:            }
676:
677:            /**
678:             * Looks up a file name based on a JRE system property and returns the associated
679:             * File object if it exists. This method adds messages with the topic prefix 
680:             * {@link #ERROR} and {@link #INFO} as appropriate, with the suffix matching the 
681:             * supplied property.
682:             * @param property the system property to look up
683:             * @return the file object, or <code>null</code> if not found
684:             */
685:            protected final File getFileFromProperty(String property) {
686:                String propertyValue = null;
687:                try {
688:                    propertyValue = System.getProperty(property);
689:                    if (propertyValue == null) {
690:                        m_session.addMessage("Error." + property,
691:                                "The system property '" + property
692:                                        + "' is null.");
693:                        return null;
694:                    }
695:
696:                    //
697:                    //  It's also possible to use "==" to mark a property.  We remove that
698:                    //  here so that we can actually find the property file, then.
699:                    //
700:                    if (propertyValue.startsWith("=")) {
701:                        propertyValue = propertyValue.substring(1);
702:                    }
703:
704:                    try {
705:                        m_session
706:                                .addMessage("Info." + property,
707:                                        "The system property '" + property
708:                                                + "' is set to: "
709:                                                + propertyValue + ".");
710:
711:                        // Prepend a file: prefix if not there already
712:                        if (!propertyValue.startsWith("file:")) {
713:                            propertyValue = "file:" + propertyValue;
714:                        }
715:                        URL url = new URL(propertyValue);
716:                        File file = new File(url.getPath());
717:                        if (file.exists()) {
718:                            m_session.addMessage("Info." + property, "File '"
719:                                    + propertyValue
720:                                    + "' exists in the filesystem.");
721:                            return file;
722:                        }
723:                    } catch (MalformedURLException e) {
724:                        // Swallow exception because we can't find it anyway
725:                    }
726:                    m_session
727:                            .addMessage(
728:                                    "Error." + property,
729:                                    "File '"
730:                                            + propertyValue
731:                                            + "' doesn't seem to exist. This might be a problem.");
732:                    return null;
733:                } catch (SecurityException e) {
734:                    m_session
735:                            .addMessage(
736:                                    "Error." + property,
737:                                    "We could not read system property '"
738:                                            + property
739:                                            + "'. This is probably because you are running with a security manager.");
740:                    return null;
741:                }
742:            }
743:
744:            /**
745:             * Verfies the Java security policy configuration. The configuration is
746:             * valid if value of the local policy (at <code>WEB-INF/jspwiki.policy</code>
747:             * resolves to an existing file, and the policy file contained therein
748:             * represents a valid policy.
749:             */
750:            protected final void verifyPolicy() {
751:                // Look up the policy file and set the status text.
752:                URL policyURL = AuthenticationManager.findConfigFile(m_engine,
753:                        AuthorizationManager.DEFAULT_POLICY);
754:                String path = policyURL.getPath();
755:                if (path.startsWith("file:")) {
756:                    path = path.substring(5);
757:                }
758:                File policyFile = new File(path);
759:
760:                // Next, verify the policy
761:                try {
762:                    // Get the file
763:                    PolicyReader policy = new PolicyReader(policyFile);
764:                    m_session.addMessage(INFO_POLICY, "The security policy '"
765:                            + policy.getFile() + "' exists.");
766:
767:                    // See if there is a keystore that's valid
768:                    KeyStore ks = policy.getKeyStore();
769:                    if (ks == null) {
770:                        m_session
771:                                .addMessage(ERROR_POLICY,
772:                                        "Policy file does not have a keystore... at least not one that we can locate.");
773:                    } else {
774:                        m_session
775:                                .addMessage(
776:                                        INFO_POLICY,
777:                                        "The security policy specifies a keystore, and we were able to locate it in the filesystem.");
778:                    }
779:
780:                    // Verify the file
781:                    policy.read();
782:                    List errors = policy.getMessages();
783:                    if (errors.size() > 0) {
784:                        for (Iterator it = errors.iterator(); it.hasNext();) {
785:                            Exception e = (Exception) it.next();
786:                            m_session.addMessage(ERROR_POLICY, e.getMessage());
787:                        }
788:                    } else {
789:                        m_session.addMessage(INFO_POLICY,
790:                                "The security policy looks fine.");
791:                        m_isSecurityPolicyConfigured = true;
792:                    }
793:
794:                    // Stash the unique principals mentioned in the file,
795:                    // plus our standard roles.
796:                    Set principals = new LinkedHashSet();
797:                    principals.add(Role.ALL);
798:                    principals.add(Role.ANONYMOUS);
799:                    principals.add(Role.ASSERTED);
800:                    principals.add(Role.AUTHENTICATED);
801:                    ProtectionDomain[] domains = policy.getProtectionDomains();
802:                    for (int i = 0; i < domains.length; i++) {
803:                        Principal[] domainPrincipals = domains[i]
804:                                .getPrincipals();
805:                        for (int j = 0; j < domainPrincipals.length; j++) {
806:                            principals.add(domainPrincipals[j]);
807:                        }
808:                    }
809:                    m_policyPrincipals = (Principal[]) principals
810:                            .toArray(new Principal[principals.size()]);
811:                } catch (IOException e) {
812:                    m_session.addMessage(ERROR_POLICY, e.getMessage());
813:                }
814:            }
815:
816:            /**
817:             * Verifies that a particular Principal possesses a Permission, as defined
818:             * in the security policy file.
819:             * @param principal the principal
820:             * @param permission the permission
821:             * @return the result, based on consultation with the active Java security
822:             *         policy
823:             */
824:            protected final boolean verifyStaticPermission(Principal principal,
825:                    final Permission permission) {
826:                Subject subject = new Subject();
827:                subject.getPrincipals().add(principal);
828:                boolean allowedByGlobalPolicy = ((Boolean) Subject
829:                        .doAsPrivileged(subject, new PrivilegedAction() {
830:                            public Object run() {
831:                                try {
832:                                    AccessController
833:                                            .checkPermission(permission);
834:                                    return Boolean.TRUE;
835:                                } catch (AccessControlException e) {
836:                                    return Boolean.FALSE;
837:                                }
838:                            }
839:                        }, null)).booleanValue();
840:
841:                if (allowedByGlobalPolicy) {
842:                    return true;
843:                }
844:
845:                // Check local policy
846:                Principal[] principals = new Principal[] { principal };
847:                return m_engine.getAuthorizationManager().allowedByLocalPolicy(
848:                        principals, permission);
849:            }
850:
851:            /**
852:             * Verifies that the user datbase was initialized properly, and that
853:             * user add and delete operations work as they should.
854:             */
855:            protected final void verifyUserDatabase() {
856:                UserDatabase db = m_engine.getUserManager().getUserDatabase();
857:
858:                // Check for obvious error conditions
859:                if (db == null) {
860:                    m_session.addMessage(ERROR_DB,
861:                            "UserDatabase is null; JSPWiki could not "
862:                                    + "initialize it. Check the error logs.");
863:                    return;
864:                }
865:
866:                if (db instanceof  UserManager.DummyUserDatabase) {
867:                    m_session
868:                            .addMessage(
869:                                    ERROR_DB,
870:                                    "UserDatabase is DummyUserDatabase; JSPWiki "
871:                                            + "may not have been able to initialize the database you supplied in "
872:                                            + "jspwiki.properties, or you left the 'jspwiki.userdatabase' property "
873:                                            + "blank. Check the error logs.");
874:                }
875:
876:                // Tell user what class of database this is.
877:                m_session.addMessage(INFO_DB, "UserDatabase is of type '"
878:                        + db.getClass().getName()
879:                        + "'. It appears to be initialized properly.");
880:
881:                // Now, see how many users we have.
882:                int oldUserCount = 0;
883:                try {
884:                    Principal[] users = db.getWikiNames();
885:                    oldUserCount = users.length;
886:                    m_session.addMessage(INFO_DB, "The user database contains "
887:                            + oldUserCount + " users.");
888:                } catch (WikiSecurityException e) {
889:                    m_session.addMessage(ERROR_DB,
890:                            "Could not obtain a list of current users: "
891:                                    + e.getMessage());
892:                    return;
893:                }
894:
895:                // Try adding a bogus user with random name
896:                String loginName = "TestUser"
897:                        + String.valueOf(System.currentTimeMillis());
898:                try {
899:                    UserProfile profile = new DefaultUserProfile();
900:                    profile.setEmail("testuser@testville.com");
901:                    profile.setLoginName(loginName);
902:                    profile.setFullname("FullName" + loginName);
903:                    profile.setPassword("password");
904:                    db.save(profile);
905:
906:                    // Make sure the profile saved successfully
907:                    if (db.getWikiNames().length == oldUserCount) {
908:                        m_session.addMessage(ERROR_DB,
909:                                "Could not add a test user to the database.");
910:                        return;
911:                    }
912:                    m_session
913:                            .addMessage(INFO_DB,
914:                                    "The user database allows new users to be created, as it should.");
915:                } catch (WikiSecurityException e) {
916:                    m_session.addMessage(ERROR_DB,
917:                            "Could not add a test user to the database: "
918:                                    + e.getMessage());
919:                    return;
920:                }
921:
922:                // Now delete the profile; should be back to old count
923:                try {
924:                    db.deleteByLoginName(loginName);
925:                    if (db.getWikiNames().length != oldUserCount) {
926:                        m_session
927:                                .addMessage(ERROR_DB,
928:                                        "Could not delete a test user from the database.");
929:                        return;
930:                    }
931:                    m_session
932:                            .addMessage(INFO_DB,
933:                                    "The user database allows users to be deleted, as it should.");
934:                } catch (WikiSecurityException e) {
935:                    m_session.addMessage(ERROR_DB,
936:                            "Could not delete a test user to the database: "
937:                                    + e.getMessage());
938:                    return;
939:                }
940:
941:                m_session.addMessage(INFO_DB,
942:                        "The user database configuration looks fine.");
943:            }
944:
945:            /**
946:             * Returns the location of the JAAS configuration file if and only if the
947:             * <code>java.security.auth.login.config</code> is set <em>and</em> the
948:             * file it points to exists in the file system; returns <code>null</code>
949:             * in all other cases.
950:             * @return the location of the JAAS configuration file
951:             */
952:            public final File jaasConfiguration() {
953:                return m_jaasConfig;
954:            }
955:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.