View Javadoc

1   /* 
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.security.impl;
18  
19  import java.security.Principal;
20  import java.sql.Date;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashSet;
24  import java.util.Iterator;
25  import java.util.LinkedList;
26  import java.util.List;
27  import java.util.Set;
28  import java.util.prefs.BackingStoreException;
29  import java.util.prefs.Preferences;
30  
31  import javax.security.auth.Subject;
32  
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  import org.apache.jetspeed.security.AuthenticationProviderProxy;
36  import org.apache.jetspeed.security.HierarchyResolver;
37  import org.apache.jetspeed.security.SecurityException;
38  import org.apache.jetspeed.security.SecurityProvider;
39  import org.apache.jetspeed.security.User;
40  import org.apache.jetspeed.security.UserManager;
41  import org.apache.jetspeed.security.UserPrincipal;
42  import org.apache.jetspeed.security.spi.SecurityMappingHandler;
43  import org.apache.jetspeed.util.ArgUtil;
44  
45  /***
46   * <p>
47   * Implementation for managing users and provides access to the {@link User}.
48   * </p>
49   * 
50   * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
51   * @version $Id: UserManagerImpl.java 516448 2007-03-09 16:25:47Z ate $
52   */
53  public class UserManagerImpl implements UserManager
54  {
55  
56      private static final Log log = LogFactory.getLog(UserManagerImpl.class);
57  
58      /*** The authenticatino provider proxy. */
59      private AuthenticationProviderProxy atnProviderProxy = null;
60  
61      /*** The security mapping handler. */
62      private SecurityMappingHandler securityMappingHandler = null;
63  
64      private String anonymousUser = "guest";
65      private User guest = null;
66      
67      /***
68       * @param securityProvider
69       *            The security provider.
70       */
71      public UserManagerImpl(SecurityProvider securityProvider)
72      {
73          this.atnProviderProxy = securityProvider
74                  .getAuthenticationProviderProxy();
75          this.securityMappingHandler = securityProvider
76                  .getSecurityMappingHandler();
77      }
78  
79      /***
80       * @param securityProvider
81       *            The security provider.
82       * @param anonymousUser
83       *            The anonymous user name
84       */
85      public UserManagerImpl(SecurityProvider securityProvider,
86              String anonymousUser)
87      {
88          this.atnProviderProxy = securityProvider
89                  .getAuthenticationProviderProxy();
90          this.securityMappingHandler = securityProvider
91                  .getSecurityMappingHandler();
92          if (anonymousUser != null)
93          {
94              this.anonymousUser = anonymousUser;
95          }
96      }
97  
98      /***
99       * @param securityProvider
100      *            The security provider.
101      * @param roleHierarchyResolver
102      *            The role hierachy resolver.
103      * @param groupHierarchyResolver
104      *            The group hierarchy resolver.
105      */
106     public UserManagerImpl(SecurityProvider securityProvider,
107             HierarchyResolver roleHierarchyResolver,
108             HierarchyResolver groupHierarchyResolver)
109     {
110         securityProvider.getSecurityMappingHandler().setRoleHierarchyResolver(
111                 roleHierarchyResolver);
112         securityProvider.getSecurityMappingHandler().setGroupHierarchyResolver(
113                 groupHierarchyResolver);
114         this.atnProviderProxy = securityProvider
115                 .getAuthenticationProviderProxy();
116         this.securityMappingHandler = securityProvider
117                 .getSecurityMappingHandler();
118     }
119 
120     /***
121      * @param securityProvider
122      *            The security provider.
123      * @param roleHierarchyResolver
124      *            The role hierachy resolver.
125      * @param groupHierarchyResolver
126      *            The group hierarchy resolver.
127      * @param anonymousUser
128      *            The anonymous user name
129      */
130     public UserManagerImpl(SecurityProvider securityProvider,
131             HierarchyResolver roleHierarchyResolver,
132             HierarchyResolver groupHierarchyResolver, String anonymousUser)
133     {
134         securityProvider.getSecurityMappingHandler().setRoleHierarchyResolver(
135                 roleHierarchyResolver);
136         securityProvider.getSecurityMappingHandler().setGroupHierarchyResolver(
137                 groupHierarchyResolver);
138         this.atnProviderProxy = securityProvider
139                 .getAuthenticationProviderProxy();
140         this.securityMappingHandler = securityProvider
141                 .getSecurityMappingHandler();
142         if (anonymousUser != null)
143         {
144             this.anonymousUser = anonymousUser;
145         }
146     }
147 
148     /*
149      * (non-Javadoc)
150      * 
151      * @see org.apache.jetspeed.security.UserManager#getAnonymousUser()
152      */
153     public String getAnonymousUser()
154     {
155         return this.anonymousUser;
156     }
157 
158     /***
159      * @see org.apache.jetspeed.security.UserManager#authenticate(java.lang.String,
160      *      java.lang.String)
161      */
162     public boolean authenticate(String username, String password)
163     {
164         ArgUtil.notNull(new Object[]
165         { username, password}, new String[]
166         { "username", "password"},
167                 "authenticate(java.lang.String, java.lang.String)");
168 
169         boolean authenticated = false;
170         try
171         {
172             if (!getAnonymousUser().equals(username))
173             {
174                 authenticated = atnProviderProxy.authenticate(username,
175                         password);
176                 if (authenticated && log.isDebugEnabled())
177                 {
178                     log.debug("Authenticated user: " + username);
179                 }
180             }
181         } catch (SecurityException e)
182         {
183             // ignore: not authenticated
184         }
185         return authenticated;
186     }
187 
188     /***
189      * @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
190      *      java.lang.String)
191      */
192     public void addUser(String username, String password)
193             throws SecurityException
194     {
195         ArgUtil.notNull(new Object[]
196         { username}, new String[]
197         { "username"}, "addUser(java.lang.String, java.lang.String)");
198 
199         createUser(username, password, atnProviderProxy
200                 .getDefaultAuthenticationProvider(),false);
201     }
202 
203     
204 
205     /***
206      * @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
207      *      java.lang.String, java.lang.String)
208      */
209     public void addUser(String username, String password, String atnProviderName)
210             throws SecurityException
211     {
212         ArgUtil.notNull(new Object[]
213         { username}, new String[]
214         { "username"}, "addUser(java.lang.String, java.lang.String)");
215 
216         createUser(username, password, atnProviderName, false);
217     }
218 
219     /***
220      * @see org.apache.jetspeed.security.UserManager#importUser(java.lang.String,
221      *      java.lang.String, boolean)
222      */
223     public void importUser(String username, String password, boolean passThrough)
224             throws SecurityException
225     {
226         ArgUtil.notNull(new Object[]
227         { username}, new String[]
228         { "username"}, "addUser(java.lang.String, java.lang.String)");
229 
230         createUser(username, password, atnProviderProxy
231                 .getDefaultAuthenticationProvider(),passThrough);
232     }
233 
234     /***
235      * @see org.apache.jetspeed.security.UserManager#importUser(java.lang.String,
236      *      java.lang.String, java.lang.String, boolean)
237      */
238     public void importUser(String username, String password, String atnProviderName, boolean passThrough)
239             throws SecurityException
240     {
241         ArgUtil.notNull(new Object[]
242         { username}, new String[]
243         { "username"}, "addUser(java.lang.String, java.lang.String)");
244 
245         createUser(username, password, atnProviderName,passThrough);
246     }
247     /***
248      * @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
249      *      java.lang.String, java.lang.String)
250      */
251     protected void createUser(String username, String password, String atnProviderName, boolean raw)
252             throws SecurityException
253     {
254         ArgUtil
255                 .notNull(new Object[]
256                 { username, atnProviderName}, new String[]
257                 { "username", "atnProviderName"},
258                         "addUser(java.lang.String, java.lang.String, java.lang.String)");
259 
260 //        if (getAnonymousUser().equals(username)) { throw new SecurityException(
261 //                SecurityException.ANONYMOUS_USER_PROTECTED.create(username)); }
262 
263         // Check if user already exists.
264         if (userExists(username)) { 
265             throw new SecurityException(SecurityException.USER_ALREADY_EXISTS.create(username));
266         }
267 
268         UserPrincipal userPrincipal = new UserPrincipalImpl(username);
269         String fullPath = userPrincipal.getFullPath();
270         // Add the preferences.
271         Preferences preferences = Preferences.userRoot().node(fullPath);
272         if (log.isDebugEnabled())
273         {
274             log.debug("Added user preferences node: " + fullPath);
275         }
276         try
277         {
278             if ((null != preferences)
279                     && preferences.absolutePath().equals(fullPath))
280             {
281                 // Add user principal.
282                 atnProviderProxy.addUserPrincipal(userPrincipal);
283                 if (password != null)
284                 {
285                     try
286                     {
287                         // Set private password credential
288                     	if (raw)
289                             atnProviderProxy.importPassword(username, password,atnProviderName);
290                     	else
291                     		atnProviderProxy.setPassword(username, null, password,atnProviderName);
292                     }
293                     catch (SecurityException se1)
294                     {
295                         try
296                         {
297                             // rollback created user
298                             atnProviderProxy.removeUserPrincipal(userPrincipal);
299                         }
300                         catch (SecurityException se2)
301                         {
302                             log.error("Failed to rollback created user after its password turned out to be invalid", se2);
303                         }
304                         throw se1;
305                     }
306                 }
307                 if (log.isDebugEnabled())
308                 {
309                     log.debug("Added user: " + fullPath);
310                 }
311             }
312         } catch (SecurityException se)
313         {
314             log.error(se.getMessage(), se);
315 
316             // Remove the preferences node.
317             try
318             {
319                 preferences.removeNode();
320             } catch (BackingStoreException bse)
321             {
322                 bse.printStackTrace();
323             }
324             throw se;
325         }
326     }
327 
328     
329     
330     /***
331      * @see org.apache.jetspeed.security.UserManager#removeUser(java.lang.String)
332      * 
333      * TODO Enforce that only administrators can do this.
334      */
335     public void removeUser(String username) throws SecurityException
336     {
337         ArgUtil.notNull(new Object[]
338         { username}, new String[]
339         { "username"}, "removeUser(java.lang.String)");
340 
341         if (getAnonymousUser().equals(username)) { throw new SecurityException(
342                 SecurityException.ANONYMOUS_USER_PROTECTED.create(username)); }
343         UserPrincipal userPrincipal = new UserPrincipalImpl(username);
344         String fullPath = userPrincipal.getFullPath();
345         atnProviderProxy.removeUserPrincipal(userPrincipal);
346         // Remove preferences
347         Preferences preferences = Preferences.userRoot().node(fullPath);
348         try
349         {
350             preferences.removeNode();
351         } catch (BackingStoreException bse)
352         {
353             bse.printStackTrace();
354         }
355     }
356 
357     /***
358      * @see org.apache.jetspeed.security.UserManager#userExists(java.lang.String)
359      */
360     public boolean userExists(String username)
361     {
362         ArgUtil.notNull(new Object[]
363         { username}, new String[]
364         { "username"}, "userExists(java.lang.String)");
365 
366         return atnProviderProxy.getUserPrincipal(username) != null;
367     }
368 
369     /***
370      * @see org.apache.jetspeed.security.UserManager#getUser(java.lang.String)
371      */
372     public User getUser(String username) throws SecurityException
373     {
374         ArgUtil.notNull(new Object[]
375         { username}, new String[]
376         { "username"}, "getUser(java.lang.String)");
377 
378         // optimize guest lookups as they can be excessive
379         if (guest != null && getAnonymousUser().equals(username))
380         {
381             // TODO: need to handle caching issues            
382             return guest;
383         }
384         
385         Set principals = new PrincipalsSet();
386         String fullPath = (new UserPrincipalImpl(username)).getFullPath();
387 
388         Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
389         if (null == userPrincipal) { 
390             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
391         }
392 
393         principals.add(userPrincipal);
394         principals.addAll(securityMappingHandler.getRolePrincipals(username));
395         principals.addAll(securityMappingHandler.getGroupPrincipals(username));
396 
397         Subject subject = null;
398         if (getAnonymousUser().equals(username))
399         {
400             subject = new Subject(true, principals, new HashSet(),
401                     new HashSet());
402         } else
403         {
404             subject = new Subject(true, principals, atnProviderProxy
405                     .getPublicCredentials(username), atnProviderProxy
406                     .getPrivateCredentials(username));
407         }
408         Preferences preferences = Preferences.userRoot().node(fullPath);
409         User user = new UserImpl(subject, preferences);
410         if (getAnonymousUser().equals(username))
411         {
412             guest = user;
413         }
414         return user;
415     }
416 
417     /***
418      * @see org.apache.jetspeed.security.UserManager#getUsers(java.lang.String)
419      */
420     public Iterator getUsers(String filter) throws SecurityException
421     {
422         List users = new LinkedList();
423         Iterator userPrincipals = atnProviderProxy.getUserPrincipals(filter)
424                 .iterator();
425         while (userPrincipals.hasNext())
426         {
427             String username = ((Principal) userPrincipals.next()).getName();
428             User user = getUser(username);
429             users.add(user);
430         }
431         return users.iterator();
432     }
433 
434     /***
435      * @see org.apache.jetspeed.security.UserManager#getUserNames(java.lang.String)
436      */
437     public Iterator getUserNames(String filter) throws SecurityException
438     {
439         List usernames = new LinkedList();
440         Iterator userPrincipals = atnProviderProxy.getUserPrincipals(filter).iterator();
441         while (userPrincipals.hasNext())
442         {
443             usernames.add(((Principal) userPrincipals.next()).getName());
444         }
445         return usernames.iterator();
446     }
447 
448     /***
449      * @see org.apache.jetspeed.security.UserManager#getUsersInRole(java.lang.String)
450      */
451     public Collection getUsersInRole(String roleFullPathName)
452             throws SecurityException
453     {
454         ArgUtil.notNull(new Object[]
455         { roleFullPathName}, new String[]
456         { "roleFullPathName"}, "getUsersInRole(java.lang.String)");
457 
458         Collection users = new ArrayList();
459 
460         Set userPrincipals = securityMappingHandler
461                 .getUserPrincipalsInRole(roleFullPathName);
462         Iterator userPrincipalsIter = userPrincipals.iterator();
463         while (userPrincipalsIter.hasNext())
464         {
465             Principal userPrincipal = (Principal) userPrincipalsIter.next();
466             users.add(getUser(userPrincipal.getName()));
467         }
468         return users;
469     }
470 
471     /***
472      * @see org.apache.jetspeed.security.UserManager#getUsersInGroup(java.lang.String)
473      */
474     public Collection getUsersInGroup(String groupFullPathName)
475             throws SecurityException
476     {
477         ArgUtil.notNull(new Object[]
478         { groupFullPathName}, new String[]
479         { "groupFullPathName"}, "getUsersInGroup(java.lang.String)");
480 
481         Collection users = new ArrayList();
482 
483         Set userPrincipals = securityMappingHandler
484                 .getUserPrincipalsInGroup(groupFullPathName);
485         Iterator userPrincipalsIter = userPrincipals.iterator();
486         while (userPrincipalsIter.hasNext())
487         {
488             Principal userPrincipal = (Principal) userPrincipalsIter.next();
489             users.add(getUser(userPrincipal.getName()));
490         }
491         return users;
492     }
493 
494     /***
495      * @see org.apache.jetspeed.security.UserManager#setPassword(java.lang.String,
496      *      java.lang.String, java.lang.String)
497      * 
498      * TODO Enforce that only administrators can do this.
499      */
500     public void setPassword(String username, String oldPassword,
501             String newPassword) throws SecurityException
502     {
503         ArgUtil
504                 .notNull(new Object[]
505                 { username, newPassword}, new String[]
506                 { "username", "newPassword"},
507                         "setPassword(java.lang.String, java.lang.String, java.lang.String)");
508 
509         if (getAnonymousUser().equals(username)) { throw new SecurityException(
510                 SecurityException.ANONYMOUS_USER_PROTECTED.create(username)); }
511         atnProviderProxy.setPassword(username, oldPassword, newPassword);
512     }
513 
514     /***
515      * @see org.apache.jetspeed.security.UserManager#setPasswordEnabled(java.lang.String,
516      *      boolean)
517      */
518     public void setPasswordEnabled(String userName, boolean enabled)
519             throws SecurityException
520     {
521         ArgUtil.notNull(new Object[]
522         { userName,}, new String[]
523         { "userName"}, "setPasswordEnabled(java.lang.String, boolean)");
524 
525         if (getAnonymousUser().equals(userName)) { throw new SecurityException(
526                 SecurityException.ANONYMOUS_USER_PROTECTED.create(userName)); }
527         atnProviderProxy.setPasswordEnabled(userName, enabled);
528     }
529 
530     /***
531      * @see org.apache.jetspeed.security.UserManager#setPasswordUpdateRequired(java.lang.String,
532      *      boolean)
533      */
534     public void setPasswordUpdateRequired(String userName,
535             boolean updateRequired) throws SecurityException
536     {
537         ArgUtil.notNull(new Object[]
538         { userName,}, new String[]
539         { "userName"}, "setPasswordUpdateRequired(java.lang.String, boolean)");
540 
541         if (getAnonymousUser().equals(userName)) { throw new SecurityException(
542                 SecurityException.ANONYMOUS_USER_PROTECTED.create(userName)); }
543         atnProviderProxy.setPasswordUpdateRequired(userName, updateRequired);
544     }
545     
546     
547     /***
548      * @see org.apache.jetspeed.security.UserManager#setUserEnabled(java.lang.String, boolean)
549      */
550     public void setUserEnabled(String userName, boolean enabled) throws SecurityException
551     {
552         ArgUtil.notNull(new Object[] { userName, }, new String[] { "userName" },
553                 "setUserEnabled(java.lang.String, boolean)");
554 
555         if (getAnonymousUser().equals(userName))
556         {
557             throw new SecurityException(SecurityException.ANONYMOUS_USER_PROTECTED.create(userName));
558         }
559 
560         UserPrincipalImpl userPrincipal = (UserPrincipalImpl)atnProviderProxy.getUserPrincipal(userName);
561         if (null == userPrincipal) 
562         { 
563             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(userName));
564         }
565         if ( enabled != userPrincipal.isEnabled() )
566         {
567             userPrincipal.setEnabled(enabled);
568             atnProviderProxy.updateUserPrincipal(userPrincipal);
569         }
570     }
571 
572     /***
573      * @see org.apache.jetspeed.security.UserManager#setPasswordExpiration(java.lang.String, java.sql.Date)
574      */
575     public void setPasswordExpiration(String userName, Date expirationDate) throws SecurityException
576     {
577         ArgUtil.notNull(new Object[]
578         { userName,}, new String[]
579         { "userName"}, "setPasswordExpiration(java.lang.String, java.sql.Date)");
580 
581         if (getAnonymousUser().equals(userName)) 
582         { 
583             throw new SecurityException(SecurityException.ANONYMOUS_USER_PROTECTED.create(userName)); 
584         }
585         atnProviderProxy.setPasswordExpiration(userName, expirationDate);
586     }
587 }