001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.security.impl;
018:
019: import java.security.Principal;
020: import java.sql.Date;
021: import java.util.ArrayList;
022: import java.util.Collection;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.LinkedList;
026: import java.util.List;
027: import java.util.Set;
028: import java.util.prefs.BackingStoreException;
029: import java.util.prefs.Preferences;
030:
031: import javax.security.auth.Subject;
032:
033: import org.apache.commons.logging.Log;
034: import org.apache.commons.logging.LogFactory;
035: import org.apache.jetspeed.security.AuthenticationProviderProxy;
036: import org.apache.jetspeed.security.HierarchyResolver;
037: import org.apache.jetspeed.security.SecurityException;
038: import org.apache.jetspeed.security.SecurityProvider;
039: import org.apache.jetspeed.security.User;
040: import org.apache.jetspeed.security.UserManager;
041: import org.apache.jetspeed.security.UserPrincipal;
042: import org.apache.jetspeed.security.spi.SecurityMappingHandler;
043: import org.apache.jetspeed.util.ArgUtil;
044:
045: /**
046: * <p>
047: * Implementation for managing users and provides access to the {@link User}.
048: * </p>
049: *
050: * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
051: * @version $Id: UserManagerImpl.java 603894 2007-12-13 11:42:22Z woonsan $
052: */
053: public class UserManagerImpl implements UserManager {
054:
055: private static final Log log = LogFactory
056: .getLog(UserManagerImpl.class);
057:
058: /** The authenticatino provider proxy. */
059: private AuthenticationProviderProxy atnProviderProxy = null;
060:
061: /** The security mapping handler. */
062: private SecurityMappingHandler securityMappingHandler = null;
063:
064: private String anonymousUser = "guest";
065: private User guest = null;
066:
067: /**
068: * Flag whether the principals's user group matches the user group to which the role has been mapped. (See SRV.12.4)
069: * If this flag is set to true, roles can be inherited to users via groups.
070: */
071: private boolean rolesInheritableViaGroups = true;
072:
073: /**
074: * @param securityProvider
075: * The security provider.
076: */
077: public UserManagerImpl(SecurityProvider securityProvider) {
078: this .atnProviderProxy = securityProvider
079: .getAuthenticationProviderProxy();
080: this .securityMappingHandler = securityProvider
081: .getSecurityMappingHandler();
082: }
083:
084: /**
085: * @param securityProvider
086: * The security provider.
087: * @param anonymousUser
088: * The anonymous user name
089: */
090: public UserManagerImpl(SecurityProvider securityProvider,
091: String anonymousUser) {
092: this .atnProviderProxy = securityProvider
093: .getAuthenticationProviderProxy();
094: this .securityMappingHandler = securityProvider
095: .getSecurityMappingHandler();
096: if (anonymousUser != null) {
097: this .anonymousUser = anonymousUser;
098: }
099: }
100:
101: /**
102: * @param securityProvider
103: * The security provider.
104: * @param roleHierarchyResolver
105: * The role hierachy resolver.
106: * @param groupHierarchyResolver
107: * The group hierarchy resolver.
108: */
109: public UserManagerImpl(SecurityProvider securityProvider,
110: HierarchyResolver roleHierarchyResolver,
111: HierarchyResolver groupHierarchyResolver) {
112: securityProvider.getSecurityMappingHandler()
113: .setRoleHierarchyResolver(roleHierarchyResolver);
114: securityProvider.getSecurityMappingHandler()
115: .setGroupHierarchyResolver(groupHierarchyResolver);
116: this .atnProviderProxy = securityProvider
117: .getAuthenticationProviderProxy();
118: this .securityMappingHandler = securityProvider
119: .getSecurityMappingHandler();
120: }
121:
122: /**
123: * @param securityProvider
124: * The security provider.
125: * @param roleHierarchyResolver
126: * The role hierachy resolver.
127: * @param groupHierarchyResolver
128: * The group hierarchy resolver.
129: * @param anonymousUser
130: * The anonymous user name
131: */
132: public UserManagerImpl(SecurityProvider securityProvider,
133: HierarchyResolver roleHierarchyResolver,
134: HierarchyResolver groupHierarchyResolver,
135: String anonymousUser) {
136: securityProvider.getSecurityMappingHandler()
137: .setRoleHierarchyResolver(roleHierarchyResolver);
138: securityProvider.getSecurityMappingHandler()
139: .setGroupHierarchyResolver(groupHierarchyResolver);
140: this .atnProviderProxy = securityProvider
141: .getAuthenticationProviderProxy();
142: this .securityMappingHandler = securityProvider
143: .getSecurityMappingHandler();
144: if (anonymousUser != null) {
145: this .anonymousUser = anonymousUser;
146: }
147: }
148:
149: /*
150: * (non-Javadoc)
151: *
152: * @see org.apache.jetspeed.security.UserManager#getAnonymousUser()
153: */
154: public String getAnonymousUser() {
155: return this .anonymousUser;
156: }
157:
158: public void setRolesInheritableViaGroups(
159: boolean rolesInheritableViaGroups) {
160: this .rolesInheritableViaGroups = rolesInheritableViaGroups;
161: }
162:
163: /**
164: * @see org.apache.jetspeed.security.UserManager#authenticate(java.lang.String,
165: * java.lang.String)
166: */
167: public boolean authenticate(String username, String password) {
168: ArgUtil.notNull(new Object[] { username, password },
169: new String[] { "username", "password" },
170: "authenticate(java.lang.String, java.lang.String)");
171:
172: boolean authenticated = false;
173: try {
174: if (!getAnonymousUser().equals(username)) {
175: authenticated = atnProviderProxy.authenticate(username,
176: password);
177: if (authenticated && log.isDebugEnabled()) {
178: log.debug("Authenticated user: " + username);
179: }
180: }
181: } catch (SecurityException e) {
182: // ignore: not authenticated
183: }
184: return authenticated;
185: }
186:
187: /**
188: * @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
189: * java.lang.String)
190: */
191: public void addUser(String username, String password)
192: throws SecurityException {
193: ArgUtil.notNull(new Object[] { username },
194: new String[] { "username" },
195: "addUser(java.lang.String, java.lang.String)");
196:
197: createUser(username, password, atnProviderProxy
198: .getDefaultAuthenticationProvider(), false);
199: }
200:
201: /**
202: * @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
203: * java.lang.String, java.lang.String)
204: */
205: public void addUser(String username, String password,
206: String atnProviderName) throws SecurityException {
207: ArgUtil.notNull(new Object[] { username },
208: new String[] { "username" },
209: "addUser(java.lang.String, java.lang.String)");
210:
211: createUser(username, password, atnProviderName, false);
212: }
213:
214: /**
215: * @see org.apache.jetspeed.security.UserManager#importUser(java.lang.String,
216: * java.lang.String, boolean)
217: */
218: public void importUser(String username, String password,
219: boolean passThrough) throws SecurityException {
220: ArgUtil.notNull(new Object[] { username },
221: new String[] { "username" },
222: "addUser(java.lang.String, java.lang.String)");
223:
224: createUser(username, password, atnProviderProxy
225: .getDefaultAuthenticationProvider(), passThrough);
226: }
227:
228: /**
229: * @see org.apache.jetspeed.security.UserManager#importUser(java.lang.String,
230: * java.lang.String, java.lang.String, boolean)
231: */
232: public void importUser(String username, String password,
233: String atnProviderName, boolean passThrough)
234: throws SecurityException {
235: ArgUtil.notNull(new Object[] { username },
236: new String[] { "username" },
237: "addUser(java.lang.String, java.lang.String)");
238:
239: createUser(username, password, atnProviderName, passThrough);
240: }
241:
242: /**
243: * @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
244: * java.lang.String, java.lang.String)
245: */
246: protected void createUser(String username, String password,
247: String atnProviderName, boolean raw)
248: throws SecurityException {
249: ArgUtil
250: .notNull(new Object[] { username, atnProviderName },
251: new String[] { "username", "atnProviderName" },
252: "addUser(java.lang.String, java.lang.String, java.lang.String)");
253:
254: // if (getAnonymousUser().equals(username)) { throw new SecurityException(
255: // SecurityException.ANONYMOUS_USER_PROTECTED.create(username)); }
256:
257: // Check if user already exists.
258: if (userExists(username)) {
259: throw new SecurityException(
260: SecurityException.USER_ALREADY_EXISTS
261: .create(username));
262: }
263:
264: UserPrincipal userPrincipal = new UserPrincipalImpl(username);
265: String fullPath = userPrincipal.getFullPath();
266: // Add the preferences.
267: Preferences preferences = Preferences.userRoot().node(fullPath);
268: if (log.isDebugEnabled()) {
269: log.debug("Added user preferences node: " + fullPath);
270: }
271: try {
272: if ((null != preferences)
273: && preferences.absolutePath().equals(fullPath)) {
274: // Add user principal.
275: atnProviderProxy.addUserPrincipal(userPrincipal);
276: if (password != null) {
277: try {
278: // Set private password credential
279: if (raw)
280: atnProviderProxy.importPassword(username,
281: password, atnProviderName);
282: else
283: atnProviderProxy.setPassword(username,
284: null, password, atnProviderName);
285: } catch (SecurityException se1) {
286: try {
287: // rollback created user
288: atnProviderProxy
289: .removeUserPrincipal(userPrincipal);
290: } catch (SecurityException se2) {
291: log
292: .error(
293: "Failed to rollback created user after its password turned out to be invalid",
294: se2);
295: }
296: throw se1;
297: }
298: }
299: if (log.isDebugEnabled()) {
300: log.debug("Added user: " + fullPath);
301: }
302: }
303: } catch (SecurityException se) {
304: log.error(se.getMessage(), se);
305:
306: // Remove the preferences node.
307: try {
308: preferences.removeNode();
309: } catch (BackingStoreException bse) {
310: bse.printStackTrace();
311: }
312: throw se;
313: }
314: }
315:
316: /**
317: * @see org.apache.jetspeed.security.UserManager#removeUser(java.lang.String)
318: *
319: * TODO Enforce that only administrators can do this.
320: */
321: public void removeUser(String username) throws SecurityException {
322: ArgUtil.notNull(new Object[] { username },
323: new String[] { "username" },
324: "removeUser(java.lang.String)");
325:
326: if (getAnonymousUser().equals(username)) {
327: throw new SecurityException(
328: SecurityException.ANONYMOUS_USER_PROTECTED
329: .create(username));
330: }
331: UserPrincipal userPrincipal = new UserPrincipalImpl(username);
332: String fullPath = userPrincipal.getFullPath();
333: atnProviderProxy.removeUserPrincipal(userPrincipal);
334: // Remove preferences
335: Preferences preferences = Preferences.userRoot().node(fullPath);
336: try {
337: preferences.removeNode();
338: } catch (BackingStoreException bse) {
339: bse.printStackTrace();
340: }
341: }
342:
343: /**
344: * @see org.apache.jetspeed.security.UserManager#userExists(java.lang.String)
345: */
346: public boolean userExists(String username) {
347: ArgUtil.notNull(new Object[] { username },
348: new String[] { "username" },
349: "userExists(java.lang.String)");
350:
351: return atnProviderProxy.getUserPrincipal(username) != null;
352: }
353:
354: /**
355: * @see org.apache.jetspeed.security.UserManager#getUser(java.lang.String)
356: */
357: public User getUser(String username) throws SecurityException {
358: ArgUtil.notNull(new Object[] { username },
359: new String[] { "username" },
360: "getUser(java.lang.String)");
361:
362: // optimize guest lookups as they can be excessive
363: if (guest != null && getAnonymousUser().equals(username)) {
364: // TODO: need to handle caching issues
365: return guest;
366: }
367:
368: Set principals = new PrincipalsSet();
369: String fullPath = (new UserPrincipalImpl(username))
370: .getFullPath();
371:
372: Principal userPrincipal = atnProviderProxy
373: .getUserPrincipal(username);
374: if (null == userPrincipal) {
375: throw new SecurityException(
376: SecurityException.USER_DOES_NOT_EXIST
377: .create(username));
378: }
379:
380: principals.add(userPrincipal);
381: principals.addAll(securityMappingHandler
382: .getRolePrincipals(username));
383: Set groupPrincipals = securityMappingHandler
384: .getGroupPrincipals(username);
385: principals.addAll(groupPrincipals);
386:
387: if (this .rolesInheritableViaGroups) {
388: for (Iterator it = groupPrincipals.iterator(); it.hasNext();) {
389: Principal groupPrincipal = (Principal) it.next();
390: Set rolePrincipalsInGroup = securityMappingHandler
391: .getRolePrincipalsInGroup(groupPrincipal
392: .getName());
393: principals.addAll(rolePrincipalsInGroup);
394: }
395: }
396:
397: Subject subject = null;
398: if (getAnonymousUser().equals(username)) {
399: subject = new Subject(true, principals, new HashSet(),
400: new HashSet());
401: } else {
402: subject = new Subject(true, principals, atnProviderProxy
403: .getPublicCredentials(username), atnProviderProxy
404: .getPrivateCredentials(username));
405: }
406: Preferences preferences = Preferences.userRoot().node(fullPath);
407: User user = new UserImpl(subject, preferences);
408: if (getAnonymousUser().equals(username)) {
409: guest = user;
410: }
411: return user;
412: }
413:
414: /**
415: * @see org.apache.jetspeed.security.UserManager#getUsers(java.lang.String)
416: */
417: public Iterator getUsers(String filter) throws SecurityException {
418: List users = new LinkedList();
419: Iterator userPrincipals = atnProviderProxy.getUserPrincipals(
420: filter).iterator();
421: while (userPrincipals.hasNext()) {
422: String username = ((Principal) userPrincipals.next())
423: .getName();
424: User user = getUser(username);
425: users.add(user);
426: }
427: return users.iterator();
428: }
429:
430: /**
431: * @see org.apache.jetspeed.security.UserManager#getUserNames(java.lang.String)
432: */
433: public Iterator getUserNames(String filter)
434: throws SecurityException {
435: List usernames = new LinkedList();
436: Iterator userPrincipals = atnProviderProxy.getUserPrincipals(
437: filter).iterator();
438: while (userPrincipals.hasNext()) {
439: usernames
440: .add(((Principal) userPrincipals.next()).getName());
441: }
442: return usernames.iterator();
443: }
444:
445: /**
446: * @see org.apache.jetspeed.security.UserManager#getUsersInRole(java.lang.String)
447: */
448: public Collection getUsersInRole(String roleFullPathName)
449: throws SecurityException {
450: ArgUtil.notNull(new Object[] { roleFullPathName },
451: new String[] { "roleFullPathName" },
452: "getUsersInRole(java.lang.String)");
453:
454: Collection users = new ArrayList();
455:
456: Set userPrincipals = securityMappingHandler
457: .getUserPrincipalsInRole(roleFullPathName);
458: Iterator userPrincipalsIter = userPrincipals.iterator();
459: while (userPrincipalsIter.hasNext()) {
460: Principal userPrincipal = (Principal) userPrincipalsIter
461: .next();
462: users.add(getUser(userPrincipal.getName()));
463: }
464: return users;
465: }
466:
467: /**
468: * @see org.apache.jetspeed.security.UserManager#getUsersInGroup(java.lang.String)
469: */
470: public Collection getUsersInGroup(String groupFullPathName)
471: throws SecurityException {
472: ArgUtil.notNull(new Object[] { groupFullPathName },
473: new String[] { "groupFullPathName" },
474: "getUsersInGroup(java.lang.String)");
475:
476: Collection users = new ArrayList();
477:
478: Set userPrincipals = securityMappingHandler
479: .getUserPrincipalsInGroup(groupFullPathName);
480: Iterator userPrincipalsIter = userPrincipals.iterator();
481: while (userPrincipalsIter.hasNext()) {
482: Principal userPrincipal = (Principal) userPrincipalsIter
483: .next();
484: users.add(getUser(userPrincipal.getName()));
485: }
486: return users;
487: }
488:
489: /**
490: * @see org.apache.jetspeed.security.UserManager#setPassword(java.lang.String,
491: * java.lang.String, java.lang.String)
492: *
493: * TODO Enforce that only administrators can do this.
494: */
495: public void setPassword(String username, String oldPassword,
496: String newPassword) throws SecurityException {
497: ArgUtil
498: .notNull(new Object[] { username, newPassword },
499: new String[] { "username", "newPassword" },
500: "setPassword(java.lang.String, java.lang.String, java.lang.String)");
501:
502: if (getAnonymousUser().equals(username)) {
503: throw new SecurityException(
504: SecurityException.ANONYMOUS_USER_PROTECTED
505: .create(username));
506: }
507: atnProviderProxy
508: .setPassword(username, oldPassword, newPassword);
509: }
510:
511: /**
512: * @see org.apache.jetspeed.security.UserManager#setPasswordEnabled(java.lang.String,
513: * boolean)
514: */
515: public void setPasswordEnabled(String userName, boolean enabled)
516: throws SecurityException {
517: ArgUtil.notNull(new Object[] { userName, },
518: new String[] { "userName" },
519: "setPasswordEnabled(java.lang.String, boolean)");
520:
521: if (getAnonymousUser().equals(userName)) {
522: throw new SecurityException(
523: SecurityException.ANONYMOUS_USER_PROTECTED
524: .create(userName));
525: }
526: atnProviderProxy.setPasswordEnabled(userName, enabled);
527: }
528:
529: /**
530: * @see org.apache.jetspeed.security.UserManager#setPasswordUpdateRequired(java.lang.String,
531: * boolean)
532: */
533: public void setPasswordUpdateRequired(String userName,
534: boolean updateRequired) throws SecurityException {
535: ArgUtil.notNull(new Object[] { userName, },
536: new String[] { "userName" },
537: "setPasswordUpdateRequired(java.lang.String, boolean)");
538:
539: if (getAnonymousUser().equals(userName)) {
540: throw new SecurityException(
541: SecurityException.ANONYMOUS_USER_PROTECTED
542: .create(userName));
543: }
544: atnProviderProxy.setPasswordUpdateRequired(userName,
545: updateRequired);
546: }
547:
548: /**
549: * @see org.apache.jetspeed.security.UserManager#setUserEnabled(java.lang.String, boolean)
550: */
551: public void setUserEnabled(String userName, boolean enabled)
552: throws SecurityException {
553: ArgUtil.notNull(new Object[] { userName, },
554: new String[] { "userName" },
555: "setUserEnabled(java.lang.String, boolean)");
556:
557: if (getAnonymousUser().equals(userName)) {
558: throw new SecurityException(
559: SecurityException.ANONYMOUS_USER_PROTECTED
560: .create(userName));
561: }
562:
563: UserPrincipalImpl userPrincipal = (UserPrincipalImpl) atnProviderProxy
564: .getUserPrincipal(userName);
565: if (null == userPrincipal) {
566: throw new SecurityException(
567: SecurityException.USER_DOES_NOT_EXIST
568: .create(userName));
569: }
570: if (enabled != userPrincipal.isEnabled()) {
571: userPrincipal.setEnabled(enabled);
572: atnProviderProxy.updateUserPrincipal(userPrincipal);
573: }
574: }
575:
576: /**
577: * @see org.apache.jetspeed.security.UserManager#setPasswordExpiration(java.lang.String, java.sql.Date)
578: */
579: public void setPasswordExpiration(String userName,
580: Date expirationDate) throws SecurityException {
581: ArgUtil
582: .notNull(new Object[] { userName, },
583: new String[] { "userName" },
584: "setPasswordExpiration(java.lang.String, java.sql.Date)");
585:
586: if (getAnonymousUser().equals(userName)) {
587: throw new SecurityException(
588: SecurityException.ANONYMOUS_USER_PROTECTED
589: .create(userName));
590: }
591: atnProviderProxy
592: .setPasswordExpiration(userName, expirationDate);
593: }
594: }
|