001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2002 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.event;
021:
022: import java.security.Principal;
023:
024: import org.apache.commons.lang.ArrayUtils;
025: import org.apache.log4j.Level;
026: import org.apache.log4j.Logger;
027:
028: import com.ecyrd.jspwiki.event.WikiEvent;
029:
030: /**
031: * <p>Event class for security events: login/logout, wiki group adds/changes, and
032: * authorization decisions. When a WikiSecurityEvent is constructed, the
033: * security logger {@link #log} is notified.</p>
034: * <p>These events are logged with priority <code>ERROR</code>:</p>
035: * <ul>
036: * <li>login failed - bad credential or password</li>
037: * </ul>
038: * <p>These events are logged with priority <code>WARN</code>:</p>
039: * <ul>
040: * <li>access denied</li>
041: * <li>login failed - credential expired</li>
042: * <li>login failed - account expired</li>
043: * </ul>
044: * <p>These events are logged with priority <code>INFO</code>:</p>
045: * <ul>
046: * <li>login succeeded</li>
047: * <li>logout</li>
048: * <li>user profile name changed</li>
049: * </ul>
050: * <p>These events are logged with priority <code>DEBUG</code>:</p>
051: * <ul>
052: * <li>access allowed</li>
053: * <li>add group</li>
054: * <li>remove group</li>
055: * <li>clear all groups</li>
056: * <li>add group member</li>
057: * <li>remove group member</li>
058: * <li>clear all members from group</li>
059: * </ul>
060: * @author Andrew Jaquith
061: * @since 2.3.79
062: */
063: public final class WikiSecurityEvent extends WikiEvent {
064:
065: private static final long serialVersionUID = -6751950399721334496L;
066:
067: /** When a user's attempts to log in as guest, via cookies, using a password or otherwise. */
068: public static final int LOGIN_INITIATED = 30;
069:
070: /** When a user first accesses JSPWiki, but before logging in or setting a cookie. */
071: public static final int LOGIN_ANONYMOUS = 31;
072:
073: /** When a user sets a cookie to assert their identity. */
074: public static final int LOGIN_ASSERTED = 32;
075:
076: /** When a user authenticates with a username and password, or via container auth. */
077: public static final int LOGIN_AUTHENTICATED = 40;
078:
079: /** When a login fails due to account expiration. */
080: public static final int LOGIN_ACCOUNT_EXPIRED = 41;
081:
082: /** When a login fails due to credential expiration. */
083: public static final int LOGIN_CREDENTIAL_EXPIRED = 42;
084:
085: /** When a login fails due to wrong username or password. */
086: public static final int LOGIN_FAILED = 43;
087:
088: /** When a user logs out. */
089: public static final int LOGOUT = 44;
090:
091: /** When a session expires. */
092: public static final int SESSION_EXPIRED = 45;
093:
094: /** When a new wiki group is added. */
095: public static final int GROUP_ADD = 46;
096:
097: /** When a wiki group is deleted. */
098: public static final int GROUP_REMOVE = 47;
099:
100: /** When all wiki groups are removed from GroupDatabase. */
101: public static final int GROUP_CLEAR_GROUPS = 48;
102:
103: /** When access to a resource is allowed. */
104: public static final int ACCESS_ALLOWED = 51;
105:
106: /** When access to a resource is allowed. */
107: public static final int ACCESS_DENIED = 52;
108:
109: /** When a user profile is saved. */
110: public static final int PROFILE_SAVE = 53;
111:
112: /** When a user profile name changes. */
113: public static final int PROFILE_NAME_CHANGED = 54;
114:
115: /** The security logging service. */
116: protected static final Logger log = Logger.getLogger("SecurityLog");
117:
118: private final Principal m_principal;
119:
120: private final Object m_target;
121:
122: private static final int[] ERROR_EVENTS = { LOGIN_FAILED };
123:
124: private static final int[] WARN_EVENTS = { LOGIN_ACCOUNT_EXPIRED,
125: LOGIN_CREDENTIAL_EXPIRED };
126:
127: private static final int[] INFO_EVENTS = { LOGIN_AUTHENTICATED,
128: SESSION_EXPIRED, LOGOUT, PROFILE_NAME_CHANGED };
129:
130: /**
131: * Constructs a new instance of this event type, which signals a security
132: * event has occurred. The <code>source</code> parameter is required, and
133: * may not be <code>null</code>. When the WikiSecurityEvent is
134: * constructed, the security logger {@link #log} is notified.
135: * @param src the source of the event, which can be any object: a wiki
136: * page, group or authentication/authentication/group manager.
137: * @param type the type of event
138: * @param principal the subject of the event, which may be <code>null</code>
139: * @param target the changed Object, which may be <code>null</code>
140: */
141: public WikiSecurityEvent(Object src, int type, Principal principal,
142: Object target) {
143: super (src, type);
144: if (src == null) {
145: throw new IllegalArgumentException(
146: "Argument(s) cannot be null.");
147: }
148: this .m_principal = principal;
149: this .m_target = target;
150: if (log.isEnabledFor(Level.ERROR)
151: && ArrayUtils.contains(ERROR_EVENTS, type)) {
152: log.error(this );
153: } else if (log.isEnabledFor(Level.WARN)
154: && ArrayUtils.contains(WARN_EVENTS, type)) {
155: log.warn(this );
156: } else if (log.isEnabledFor(Level.INFO)
157: && ArrayUtils.contains(INFO_EVENTS, type)) {
158: log.info(this );
159: }
160: log.debug(this );
161: }
162:
163: /**
164: * Constructs a new instance of this event type, which signals a security
165: * event has occurred. The <code>source</code> parameter is required, and
166: * may not be <code>null</code>. When the WikiSecurityEvent is
167: * constructed, the security logger {@link #log} is notified.
168: * @param src the source of the event, which can be any object: a wiki
169: * page, group or authentication/authentication/group manager.
170: * @param type the type of event
171: * @param target the changed Object, which may be <code>null</code>.
172: */
173: public WikiSecurityEvent(Object src, int type, Object target) {
174: this (src, type, null, target);
175: }
176:
177: /**
178: * Returns the principal to whom the opeation applied, if supplied. This
179: * method may return <code>null</code>
180: * <em>— and calling methods should check for this condition</em>.
181: * @return the changed object
182: */
183: public final Object getPrincipal() {
184: return m_principal;
185: }
186:
187: /**
188: * Returns the object that was operated on, if supplied. This method may
189: * return <code>null</code>
190: * <em>— and calling methods should check for this condition</em>.
191: * @return the changed object
192: */
193: public final Object getTarget() {
194: return m_target;
195: }
196:
197: /**
198: * Prints a String (human-readable) representation of this object.
199: * @see java.lang.Object#toString()
200: */
201: public final String toString() {
202: StringBuffer msg = new StringBuffer();
203: msg.append("WikiSecurityEvent.");
204: msg.append(eventName(getType()));
205: msg.append(" [source=" + getSource().toString());
206: if (m_principal != null) {
207: msg
208: .append(", princpal="
209: + m_principal.getClass().getName());
210: msg.append(" " + m_principal.getName());
211: }
212: msg.append(", target=" + m_target);
213: msg.append("]");
214: return msg.toString();
215: }
216:
217: /**
218: * Returns a textual representation of an event type.
219: * @param type the type
220: * @return the string representation
221: */
222: public final String eventName(int type) {
223: switch (type) {
224: case LOGIN_AUTHENTICATED:
225: return "LOGIN_AUTHENTICATED";
226: case LOGIN_ACCOUNT_EXPIRED:
227: return "LOGIN_ACCOUNT_EXPIRED";
228: case LOGIN_CREDENTIAL_EXPIRED:
229: return "LOGIN_ACCOUNT_EXPIRED";
230: case LOGIN_FAILED:
231: return "LOGIN_FAILED";
232: case LOGOUT:
233: return "LOGOUT";
234: case SESSION_EXPIRED:
235: return "SESSION_EXPIRED";
236: case GROUP_ADD:
237: return "GROUP_ADD";
238: case GROUP_REMOVE:
239: return "GROUP_REMOVE";
240: case GROUP_CLEAR_GROUPS:
241: return "GROUP_CLEAR_GROUPS";
242: case ACCESS_ALLOWED:
243: return "ACCESS_ALLOWED";
244: case ACCESS_DENIED:
245: return "ACCESS_DENIED";
246: case PROFILE_NAME_CHANGED:
247: return "PROFILE_NAME_CHANGED";
248: case PROFILE_SAVE:
249: return "PROFILE_SAVE";
250: default:
251: return super .eventName();
252: }
253: }
254:
255: /**
256: * Returns a human-readable description of the event type.
257: *
258: * @return a String description of the type
259: */
260: public final String getTypeDescription() {
261: switch (getType()) {
262: case LOGIN_AUTHENTICATED:
263: return "login authenticated";
264: case LOGIN_ACCOUNT_EXPIRED:
265: return "login failed: expired account";
266: case LOGIN_CREDENTIAL_EXPIRED:
267: return "login failed: credential expired";
268: case LOGIN_FAILED:
269: return "login failed";
270: case LOGOUT:
271: return "user logged out";
272: case SESSION_EXPIRED:
273: return "session expired";
274: case GROUP_ADD:
275: return "new group added";
276: case GROUP_REMOVE:
277: return "group removed";
278: case GROUP_CLEAR_GROUPS:
279: return "all groups cleared";
280: case ACCESS_ALLOWED:
281: return "access allowed";
282: case ACCESS_DENIED:
283: return "access denied";
284: case PROFILE_NAME_CHANGED:
285: return "user profile name changed";
286: case PROFILE_SAVE:
287: return "user profile saved";
288: default:
289: return super.getTypeDescription();
290: }
291: }
292:
293: }
|