1 19 20 package com.sslexplorer.security; 21 22 import java.net.InetAddress ; 23 import java.net.UnknownHostException ; 24 import java.text.SimpleDateFormat ; 25 import java.util.ArrayList ; 26 import java.util.Date ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 32 import javax.servlet.http.Cookie ; 33 import javax.servlet.http.HttpServletRequest ; 34 import javax.servlet.http.HttpServletResponse ; 35 import javax.servlet.http.HttpSession ; 36 import javax.servlet.http.HttpSessionBindingEvent ; 37 import javax.servlet.http.HttpSessionBindingListener ; 38 39 import org.apache.commons.logging.Log; 40 import org.apache.commons.logging.LogFactory; 41 import org.apache.struts.action.Action; 42 import org.apache.struts.action.ActionForward; 43 import org.apache.struts.action.ActionMapping; 44 import org.apache.struts.util.MessageResources; 45 46 import com.sslexplorer.boot.ContextHolder; 47 import com.sslexplorer.boot.DefaultPropertyDefinition; 48 import com.sslexplorer.boot.HostService; 49 import com.sslexplorer.boot.HttpConstants; 50 import com.sslexplorer.boot.PropertyClassManager; 51 import com.sslexplorer.boot.RequestHandlerRequest; 52 import com.sslexplorer.boot.RequestHandlerResponse; 53 import com.sslexplorer.core.CoreAttributeConstants; 54 import com.sslexplorer.core.CoreEvent; 55 import com.sslexplorer.core.CoreEventConstants; 56 import com.sslexplorer.core.CoreServlet; 57 import com.sslexplorer.core.CoreUtil; 58 import com.sslexplorer.core.GlobalWarning; 59 import com.sslexplorer.core.PageInterceptException; 60 import com.sslexplorer.core.PageInterceptListener; 61 import com.sslexplorer.core.ServletRequestAdapter; 62 import com.sslexplorer.core.ServletResponseAdapter; 63 import com.sslexplorer.core.UserDatabaseManager; 64 import com.sslexplorer.policyframework.PolicyDatabaseFactory; 65 import com.sslexplorer.policyframework.PolicyUtil; 66 import com.sslexplorer.policyframework.ResourceUtil; 67 import com.sslexplorer.properties.ProfilesFactory; 68 import com.sslexplorer.properties.ProfilesListDataSource; 69 import com.sslexplorer.properties.Property; 70 import com.sslexplorer.properties.PropertyProfile; 71 import com.sslexplorer.properties.impl.realms.RealmKey; 72 import com.sslexplorer.properties.impl.systemconfig.SystemConfigKey; 73 import com.sslexplorer.properties.impl.systemconfig.SystemConfiguration; 74 import com.sslexplorer.properties.impl.userattributes.UserAttributeKey; 75 import com.sslexplorer.realms.Realm; 76 import com.sslexplorer.security.actions.PromptForPrivateKeyPassphraseDispatchAction; 77 import com.sslexplorer.security.actions.UpdatePrivateKeyPassphraseDispatchAction; 78 import com.sslexplorer.setup.SystemInformationProvider; 79 import com.sslexplorer.setup.SystemInformationRegistry; 80 import com.sslexplorer.util.TicketGenerator; 81 82 91 public class DefaultLogonController implements LogonController { 92 protected static Log log = LogFactory.getLog(DefaultLogonController.class); 93 HashMap logons = new HashMap (); 94 Map <String , SessionInfo> logonsBySessionId = new HashMap <String , SessionInfo>(); 95 96 int sessionTimeoutBlockId; 97 HashMap lockedUsers = new HashMap (); 98 List authenticationModules; 99 HashMap authorizedTickets = new HashMap (); 100 101 104 public DefaultLogonController() { 105 lockedUsers = new HashMap (); 106 107 PropertyClassManager.getInstance() 108 .getPropertyClass(SystemConfiguration.NAME) 109 .registerPropertyDefinition(new DefaultPropertyDefinition(DefaultPropertyDefinition.TYPE_INTEGER, 110 "security.maxUserCount", 111 "", 112 99999, 113 "0", 114 2, 115 true)); 116 117 SystemInformationRegistry.getInstance().registerProvider(new MostUsersOnline()); 118 SystemInformationRegistry.getInstance().registerProvider(new CurrentUsersOnline()); 119 } 120 121 126 public void init() { 127 128 } 129 130 135 public boolean isAdministrator(User principal) { 136 if (ContextHolder.getContext().isSetupMode()) { 138 return true; 139 } 140 try { 141 if (principal == null) { 143 log.error("NULL principal object passed to isAdministrator!"); 144 return false; 145 } 146 147 if (principal.getPrincipalName() == null) { 148 log.error("NULL principal name in principal object passed to isAdministrator!"); 149 return false; 150 } 151 152 List administrators = Property.getPropertyList(new RealmKey("security.administrators", principal.getRealm() 153 .getResourceId())); 154 155 for (Iterator it = administrators.iterator(); it.hasNext();) { 156 if (principal.getPrincipalName().equals((String ) it.next())) 157 return true; 158 } 159 } catch (Exception e) { 160 log.error("Failed to determine administrator status.", e); 161 } 162 return false; 163 } 164 165 171 public synchronized int addSessionTimeoutBlock(HttpSession session, String reason) { 172 Map sessionTimeoutBlocks = (Map ) session.getAttribute(Constants.SESSION_TIMEOUT_BLOCKS); 173 if (sessionTimeoutBlocks == null) { 174 sessionTimeoutBlocks = new HashMap (); 175 session.setAttribute(Constants.SESSION_TIMEOUT_BLOCKS, sessionTimeoutBlocks); 176 } 177 sessionTimeoutBlocks.put(String.valueOf(++sessionTimeoutBlockId), reason); 178 if (log.isDebugEnabled()) 179 log.debug("Preventing session timeout on session " + session.getId() 180 + " (id of " 181 + sessionTimeoutBlockId 182 + ") because '" 183 + reason 184 + "'. There are now " 185 + sessionTimeoutBlocks.size() 186 + " reasons not to timeout the session."); 187 session.setMaxInactiveInterval(-1); 188 return sessionTimeoutBlockId; 189 } 190 191 197 public synchronized void removeSessionTimeoutBlock(HttpSession session, int sessionTimeoutBlockId) { 198 try { 199 Map sessionTimeoutBlocks = (Map ) session.getAttribute(Constants.SESSION_TIMEOUT_BLOCKS); 200 if (sessionTimeoutBlocks != null) { 201 String reason = (String ) sessionTimeoutBlocks.get(String.valueOf(sessionTimeoutBlockId)); 202 if (reason == null) { 203 log.warn("No session timeout block with id of " + sessionTimeoutBlockId); 204 } else { 205 sessionTimeoutBlocks.remove(String.valueOf(sessionTimeoutBlockId)); 206 if (log.isDebugEnabled()) 207 log.debug("Removing session timeout block " + sessionTimeoutBlockId 208 + " for session " 209 + session.getId() 210 + " ('" 211 + reason 212 + "'). There are now " 213 + sessionTimeoutBlocks.size() 214 + " reasons not to timeout the session."); 215 } 216 if (sessionTimeoutBlocks.size() == 0) { 217 session.removeAttribute(Constants.SESSION_TIMEOUT_BLOCKS); 218 User user = (User) session.getAttribute(Constants.USER); 219 int minutes = CoreUtil.getUsersProfilePropertyInt(session, "webServer.sessionInactivityTimeout", user); 220 if (log.isDebugEnabled()) 221 log.debug("Initialising timeout for session " + session.getId() + " to " + minutes + " minutes"); 222 session.setMaxInactiveInterval(minutes == 0 ? -1 : minutes * 60); 223 } 224 } 225 } catch (IllegalStateException ise) { 226 log.warn("Couldnt remove session timeout block.", ise); 227 } 228 } 229 230 public void logoffSession(HttpServletRequest request, HttpServletResponse response) throws SecurityErrorException { 231 if (log.isInfoEnabled()) 232 log.info("Logging off session " + request.getSession().getId()); 233 if (request.getSession().getAttribute(Constants.LOGON_TICKET) == null) { 234 throw new SecurityErrorException(SecurityErrorException.INTERNAL_ERROR, "The current session does not contain a logon ticket"); 235 } else { 236 String ticket = (String ) request.getSession().getAttribute(Constants.LOGON_TICKET); 237 SessionInfo session = getSessionInfo(ticket); 238 logoff(ticket); 239 240 if (request.getCookies() != null) { 241 for (int i = 0; i < request.getCookies().length; i++) { 242 Cookie cookie = request.getCookies()[i]; 243 if (cookie.getName().equals(Constants.LOGON_TICKET) || cookie.getName().equals(Constants.DOMAIN_LOGON_TICKET)) { 244 cookie.setMaxAge(0); 245 response.addCookie(cookie); 246 } 247 } 248 } 249 request.getSession().removeAttribute(Constants.LOGON_TICKET); 250 session.invalidate(); 251 } 252 } 253 254 public List getSessionInfo(String username, int sessionType) { 255 List info = null; 256 for (Iterator i = logons.entrySet().iterator(); i.hasNext();) { 257 Map.Entry entry = (Map.Entry ) i.next(); 258 SessionInfo inf = (SessionInfo) entry.getValue(); 259 if (inf.getUser().getPrincipalName().equals(username) && (sessionType == -1 || (sessionType != -1 && sessionType == inf.getType()))) { 260 if (info == null) { 261 info = new ArrayList (); 262 } 263 info.add(inf); 264 } 265 } 266 return info; 267 } 268 269 public int getUserStatus(User user) throws Exception { 270 if (user != null && lockedUsers.containsKey(user.getPrincipalName()) 271 && ((AccountLock) lockedUsers.get(user.getPrincipalName())).getLocks() > 0) { 272 return ACCOUNT_LOCKED; 273 } else if (getSessionInfo(user.getPrincipalName(), -1) != null) { 274 return ACCOUNT_ACTIVE; 275 } else { 276 if (user == null) { 277 return ACCOUNT_UNKNOWN; 278 } else { 279 boolean disabled = !PolicyUtil.isEnabled(user); 280 if (disabled) { 282 return ACCOUNT_DISABLED; 283 } else { 284 boolean logonAuthorized = PolicyUtil.canLogin(user); 286 if (!logonAuthorized) { 288 return ACCOUNT_REVOKED; 289 } else { 290 return ACCOUNT_GRANTED; 291 } 292 } 293 } 294 } 295 } 296 297 private void checkForMultipleSessions(User user, InetAddress address, int sessionType) throws UserDatabaseException { 298 int type = Property.getPropertyInt(new RealmKey("security.multipleSessions", user.getRealm().getResourceId())); 299 List activeSessions; 300 switch (type) { 301 case 0: 302 break; case 1: 304 activeSessions = getSessionInfo(user.getPrincipalName(), sessionType); 305 if (activeSessions != null) { 306 throw new UserDatabaseException("You are already logged on, and this systems policy is to only allow one session per user."); 307 } 308 break; 309 case 2: 310 activeSessions = getSessionInfo(user.getPrincipalName(), sessionType); 311 if (activeSessions != null) { 312 for (Iterator i = activeSessions.iterator(); i.hasNext();) { 313 SessionInfo info = (SessionInfo) i.next(); 314 if (!info.getAddress().equals(address)) { 315 throw new UserDatabaseException("You are already logged on at a different address, and this systems policy is to only allow one session per user / address."); 316 } 317 } 318 } 319 break; 320 default: 321 throw new UserDatabaseException("Unknown multiple session restrictions type " + type + "."); 322 } 323 } 324 325 public void initialiseSession(HttpSession session, User user) throws UserDatabaseException { 326 if (log.isInfoEnabled()) 327 log.info("Initialising session " + session.getId() 328 + " with user " 329 + (user == null ? "[none]" : user.getPrincipalName())); 330 PropertyProfile profile = (PropertyProfile) session.getAttribute(Constants.SELECTED_PROFILE); 331 session.setAttribute(Constants.USER, user); 332 String logonInfo = MessageResources.getMessageResources("com.sslexplorer.navigation.ApplicationResources") 333 .getMessage("footer.info", 334 user.getPrincipalName(), 335 SimpleDateFormat.getDateTimeInstance().format(new Date ())); 336 session.setAttribute(Constants.LOGON_INFO, logonInfo); 337 try { 338 List profiles = ResourceUtil.filterResources(user, ProfilesFactory.getInstance() 339 .getPropertyProfiles(user.getPrincipalName(), true, user.getRealm().getResourceId()), true); 340 session.setAttribute(Constants.PROFILES, profiles); 341 if (profiles.size() == 0) { 342 throw new UserDatabaseException("You do not have permission to use any profiles."); 343 } 344 String startupProfile = Property.getProperty(new UserAttributeKey(user, User.USER_STARTUP_PROFILE)); 345 if (profiles.size() < 2) { 346 profile = (PropertyProfile) profiles.get(0); 347 } else if (!startupProfile.equals(ProfilesListDataSource.SELECT_ON_LOGIN)) { 348 int profileId = Integer.parseInt(startupProfile); 349 profile = null; 350 for (Iterator i = profiles.iterator(); i.hasNext();) { 351 PropertyProfile p = (PropertyProfile) i.next(); 352 if (profileId == p.getResourceId()) { 353 profile = p; 354 break; 355 } 356 } 357 if (profile == null) { 358 profile = ProfilesFactory.getInstance().getPropertyProfile(null, 359 "Default", 360 UserDatabaseManager.getInstance().getDefaultUserDatabase().getRealm().getResourceId()); 361 } 362 } 363 if (profile != null) { 364 if (log.isInfoEnabled()) 365 log.info("Switching user " + user.getPrincipalName() + " to profile " + profile.getResourceName()); 366 session.setAttribute(Constants.SELECTED_PROFILE, profile); 367 } 368 } catch (Exception e) { 369 throw new UserDatabaseException("Failed to initialise profiles.", e); 370 } 371 final String logonTicket = (String ) session.getAttribute(Constants.LOGON_TICKET); 372 session.setAttribute(Constants.LOGOFF_HOOK, new HttpSessionBindingListener () { 373 public void valueBound(HttpSessionBindingEvent evt) { 374 } 375 376 public void valueUnbound(HttpSessionBindingEvent evt) { 377 if (log.isDebugEnabled()) 378 log.debug("Session unbound"); 379 SessionInfo currentTicketSessionInfo = ((SessionInfo) logons.get(logonTicket)); 383 if (currentTicketSessionInfo == null || evt.getSession().getId().equals(currentTicketSessionInfo.getHttpSession() 384 .getId())) { 385 if (log.isDebugEnabled()) 386 log.debug("Session (" + evt.getSession().getId() 387 + ") unbound is the current session for ticket " 388 + logonTicket 389 + " so a logoff will be performed."); 390 logoff(logonTicket); 391 } else { 392 if (log.isDebugEnabled()) 393 log.debug("Session unbound is NOT the current session, ignoring."); 394 } 395 } 396 }); 397 if (log.isDebugEnabled()) 398 log.debug("Using profile: " + (profile == null ? "DEFAULT" : profile.getResourceName()) + ")"); 399 session.removeAttribute(Constants.SESSION_LOCKED); 400 401 List servletContextGlabalWarnings = (List ) session.getServletContext().getAttribute(Constants.SESSION_GLOBAL_WARNINGS); 403 if (servletContextGlabalWarnings != null) { 404 Iterator iter = servletContextGlabalWarnings.iterator(); 405 while (iter.hasNext()) { 406 GlobalWarning gw = (GlobalWarning) iter.next(); 407 try { 408 if (gw.getType() == GlobalWarning.SUPER_USER && isAdministrator(user)) { 409 CoreUtil.addSingleSessionGlobalWarning(session, gw.getMessage()); 410 } else if (gw.getType() == GlobalWarning.MANAGEMENT_USERS && PolicyDatabaseFactory.getInstance() 411 .isAnyAccessRightAllowed(user, true, true, false)) { 412 CoreUtil.addSingleSessionGlobalWarning(session, gw.getMessage()); 413 } else if (gw.getType() == GlobalWarning.USERS_WITH_PERMISSIONS && PolicyDatabaseFactory.getInstance() 414 .isPermitted(gw.getRequiredResourceType(), gw.getRequiredPermissions(), user, false)) { 415 CoreUtil.addSingleSessionGlobalWarning(session, gw.getMessage()); 416 } else if (gw.getType() == GlobalWarning.ALL_USERS) { 417 CoreUtil.addSingleSessionGlobalWarning(session, gw.getMessage()); 418 } 419 } catch (Exception e) { 420 log.error("Failed to add global message. ", e); 421 } 422 } 423 } 424 425 resetSessionTimeout(user, profile, session); 426 } 427 428 public void resetSessionTimeout(User user, PropertyProfile profile, HttpSession session) { 429 try { 430 Map sessionTimeoutBlocks = (Map ) session.getAttribute(Constants.SESSION_TIMEOUT_BLOCKS); 431 int minutes = 0; 432 if (sessionTimeoutBlocks == null || sessionTimeoutBlocks.size() == 0) { 433 minutes = CoreUtil.getUsersProfilePropertyInt(session, "webServer.sessionInactivityTimeout", user); 434 } 435 if (log.isDebugEnabled()) 436 log.debug("Resetting timeout for session " + session.getId() + " to " + minutes + " minutes"); 437 session.setMaxInactiveInterval(minutes == 0 ? -1 : minutes * 60); 438 } catch (Exception e) { 439 log.error("Failed to reset session timeout.", e); 440 } 441 } 442 443 public AccountLock checkForAccountLock(String username, String realmName) throws SecurityErrorException, 444 AccountLockedException { 445 int maxLogonAttemptsBeforeLock = 0; 447 int lockDuration = 0; 448 Realm realm; 449 try { 450 realm = UserDatabaseManager.getInstance().getRealm(realmName); 451 } catch (Exception e1) { 452 throw new SecurityErrorException(SecurityErrorException.INTERNAL_ERROR, e1, "Failed to determine the realm name " + realmName + "."); 453 } 454 455 try { 456 maxLogonAttemptsBeforeLock = Property.getPropertyInt(new RealmKey("security.maxLogonAttemptsBeforeLock", 457 realm.getResourceId())); 458 lockDuration = Property.getPropertyInt(new RealmKey("security.lockDuration", realm.getResourceId())); 459 } catch (Exception e) { 460 throw new SecurityErrorException(SecurityErrorException.INTERNAL_ERROR, e, "Failed to determine password lockout policy."); 461 } 462 AccountLock lock = "true".equals(System.getProperty("sslexplorer.recoveryMode", "false")) ? null 464 : (AccountLock) lockedUsers.get(username); 465 if (lock != null && maxLogonAttemptsBeforeLock > 0 && lockDuration > 0 && lock.getLockedTime() != -1) { 467 long expires = lock.getLockedTime() + (1000 * lockDuration); 468 long now = System.currentTimeMillis(); 469 if (now < expires) { 470 throw new AccountLockedException(username, "Account temporarily locked. Please try later.", false, expires - now); 471 } 472 lock.setAttempts(0); 474 lock.setLockedTime(-1); 475 } 476 return lock; 477 } 478 479 561 public AccountLock logonFailed(String username, String realmName, AccountLock lock) throws SecurityErrorException, 562 AccountLockedException { 563 int maxLogonAttemptsBeforeLock = 0; 565 int maxLocksBeforeDisable = 0; 566 int lockDuration = 0; 567 UserDatabase udb = null; 568 try { 569 udb = UserDatabaseManager.getInstance().getUserDatabase(realmName); 570 } catch (Exception e1) { 571 throw new SecurityErrorException(SecurityErrorException.INTERNAL_ERROR, e1, "Failed to determine the realm name " + realmName + "."); 572 } 573 574 try { 575 maxLogonAttemptsBeforeLock = Property.getPropertyInt(new RealmKey("security.maxLogonAttemptsBeforeLock", udb.getRealm() 576 .getResourceId())); 577 maxLocksBeforeDisable = Property.getPropertyInt(new RealmKey("security.maxLocksBeforeDisable", udb.getRealm() 578 .getResourceId())); 579 lockDuration = Property.getPropertyInt(new RealmKey("security.lockDuration", udb.getRealm().getResourceId())); 580 } catch (Exception e) { 581 throw new SecurityErrorException(SecurityErrorException.INTERNAL_ERROR, e, "Failed to determine password lockout policy."); 582 } 583 if (lock == null && maxLogonAttemptsBeforeLock > 0 && lockDuration > 0) { 584 lock = createLock(username); 585 } 586 if (lock != null) { 587 lock.setAttempts(lock.getAttempts() + 1); 588 if (lock.getAttempts() >= maxLogonAttemptsBeforeLock) { 589 lock.setLocks(lock.getLocks() + 1); 590 if (lock.getLocks() >= maxLocksBeforeDisable) { 591 try { 592 User user = udb.getAccount(username); 594 if (PolicyUtil.isEnabled(user)) { 595 PolicyUtil.setEnabled(user, false, lock, null); 596 } 597 } catch (Exception e) { 598 log.error(e); 599 } 600 throw new AccountLockedException(username, "Account disabled, please contact your administrator.", true, 0); 601 } else { 602 lock.setLockedTime(System.currentTimeMillis()); 603 throw new AccountLockedException(username, "Account temporarily locked. Please try later.", false, lockDuration * 1000); 604 } 605 } 606 } 607 return lock; 608 } 609 610 public void logoff(String ticket) { 611 612 SessionInfo session = (SessionInfo) logons.remove(ticket); 613 617 if(session==null) 618 return; 619 620 if (log.isInfoEnabled()) 621 log.info("Logging off " + ticket); 622 List <String > ticketsToRemove = new ArrayList <String >(); 623 synchronized (logonsBySessionId) { 624 for (Map.Entry <String , SessionInfo> entry : logonsBySessionId.entrySet()) { 625 if (entry.getValue().getLogonTicket().equals(ticket)) { 626 ticketsToRemove.add(entry.getKey()); 627 } 628 } 629 for (String key : ticketsToRemove) { 630 logonsBySessionId.remove(key); 631 } 632 } 633 if (session != null) { 634 session.release(); 635 } 636 CoreServlet.getServlet().fireCoreEvent(new CoreEvent(this, CoreEventConstants.LOGOFF, null, session)); 637 } 638 639 public Map getActiveSessions() { 640 return logons; 641 } 642 643 public User getUser(HttpSession session, String logonTicket) throws SecurityErrorException { 644 if (logonTicket == null) { 645 logonTicket = (String ) session.getAttribute(Constants.LOGON_TICKET); 646 } 647 if (logonTicket == null) { 648 throw new SecurityErrorException(SecurityErrorException.ERR_INVALID_TICKET, "No ticket was provided or found in the session object (" + session.getId() + ")"); 649 } 650 SessionInfo info = (SessionInfo) logons.get(logonTicket); 651 if (info == null) { 652 throw new SecurityErrorException(SecurityErrorException.ERR_INVALID_TICKET, "No session info. object could be found for the ticket (" + session.getId() + ")"); 653 } 654 User user = info.getUser(); 655 return user; 656 } 657 658 public User getUser(HttpServletRequest request) throws SecurityErrorException { 659 return getUser(request, null); 660 } 661 662 public User getUser(HttpServletRequest request, String logonTicket) throws SecurityErrorException { 663 return getUser(request.getSession(), logonTicket); 664 } 665 666 public int hasClientLoggedOn(HttpServletRequest request, HttpServletResponse response) throws SecurityErrorException { 667 String logonCookie = null; 669 if (request.getCookies() != null) { 670 for (int i = 0; i < request.getCookies().length; i++) { 671 Cookie cookie = request.getCookies()[i]; 672 if (cookie.getName().equals(Constants.LOGON_TICKET) || cookie.getName().equals(Constants.DOMAIN_LOGON_TICKET)) { 673 logonCookie = cookie.getValue(); 674 } 675 } 676 } 677 if (request.getAttribute(Constants.LOGON_TICKET) != null) 680 logonCookie = (String ) request.getAttribute(Constants.LOGON_TICKET); 681 String sessionLogonTicket = (String ) request.getSession().getAttribute(Constants.LOGON_TICKET); 683 if (sessionLogonTicket != null) { 684 692 700 if (logonCookie == null) { 701 702 SessionInfo session = getSessionInfo(sessionLogonTicket); 703 if (session == null) 704 return NOT_LOGGED_ON; 705 addCookies(new ServletRequestAdapter(request), new ServletResponseAdapter(response), sessionLogonTicket, session); 706 } 707 if (logonCookie != null && !sessionLogonTicket.equals(logonCookie)) { 709 log.warn("Expected a different logon ticket."); 710 return NOT_LOGGED_ON; 711 } 712 713 if(checkRemoteAddress(sessionLogonTicket, request.getRemoteAddr())) { 714 return LOGGED_ON; 715 } 716 } else { 717 if (logonCookie != null && logons.containsKey(logonCookie)) { 718 if(checkRemoteAddress(logonCookie, request.getRemoteAddr())) { 719 refreshLogonTicket(request, response, logonCookie); 720 return LOGGED_ON; 721 } 722 } 723 } 724 return NOT_LOGGED_ON; 725 } 726 727 private boolean checkRemoteAddress(String logonTicket, String remoteAddr) { 728 729 try { 730 SessionInfo session = getSessionInfo(logonTicket); 731 732 if(Property.getPropertyBoolean(new RealmKey("security.checkRemoteAddress", session.getRealmId()))) { 733 InetAddress addr = InetAddress.getByName(remoteAddr); 734 if(log.isDebugEnabled()) 735 log.debug("Verifying " + addr.getHostAddress() + " is original address " + session.getAddress().getHostAddress()); 736 return session!=null && session.getAddress().equals(addr); 737 } else 738 return true; 739 740 } catch (UnknownHostException e) { 741 log.error("Failed to determine remote address", e); 742 return false; 743 } 744 } 745 746 private void refreshLogonTicket(HttpServletRequest request, HttpServletResponse response, String logonTicket) 747 throws SecurityErrorException { 748 if (log.isInfoEnabled()) 749 log.info("Refreshing logon ticket " + logonTicket); 750 User user = getUser(request, logonTicket); 751 request.getSession().setAttribute(Constants.USER, user); 752 request.getSession().setAttribute(Constants.LOGON_TICKET, logonTicket); 753 request.setAttribute(Constants.LOGON_TICKET, logonTicket); 754 SessionInfo info = (SessionInfo) logons.get(logonTicket); 755 if (info == null) { 756 InetAddress address; 757 try { 758 address = InetAddress.getByName(request.getRemoteAddr()); 759 } catch (UnknownHostException uhe) { 760 throw new SecurityErrorException(SecurityErrorException.ERR_INVALID_TICKET, "Could not refresh logon ticket. " + uhe.getMessage()); 761 } 762 String userAgent = request.getHeader("User-Agent"); 763 info = SessionInfo.nextSession(request.getSession(), logonTicket, user, address, SessionInfo.UI, userAgent); 764 } else { 765 moveSessionTimeoutBlocks(info.getHttpSession(), request.getSession()); 766 info.setSession(request.getSession()); 767 } 768 request.getSession().setAttribute(Constants.SESSION_INFO, info); 769 770 774 try { 775 String sessionIdentifier = System.getProperty("sslexplorer.cookie", "JSESSIONID"); 776 String sessionId = null; 777 Cookie [] cookies = request.getCookies(); 778 for (int i = 0; i < cookies.length; i++) { 779 if (cookies[i].getName().equalsIgnoreCase(sessionIdentifier)) { 780 sessionId = cookies[i].getValue(); 781 break; 782 } 783 } 784 if (sessionId != null) { 785 logonsBySessionId.put(sessionId, info); 786 } else 787 log.warn("Could not find session id using identifier " + sessionIdentifier + " in HTTP request"); 788 } catch (Exception ex) { 789 log.warn("Failed to determine HTTP session id", ex); 790 } 791 addSession(logonTicket, info, request, response); 792 try { 793 if (Property.getPropertyBoolean(new SystemConfigKey("security.session.lockSessionOnBrowserClose"))) { 794 if (log.isInfoEnabled()) 795 log.info("New session - will force the user to authenticate again"); 796 request.getSession().setAttribute(Constants.SESSION_LOCKED, user); 797 } 798 } catch (Exception e) { 799 log.warn("Failed to set session lock.", e); 800 } 801 } 802 803 public void addSession(String logonTicket, SessionInfo info, HttpServletRequest request, HttpServletResponse response) { 804 logons.put(logonTicket, info); 805 addCookies(new ServletRequestAdapter(request), new ServletResponseAdapter(response), logonTicket, info); 806 } 807 808 public void addCookies(RequestHandlerRequest request, RequestHandlerResponse response, String logonTicket, SessionInfo session) { 809 810 811 if(request.getAttribute("sslx.logon.cookie")!=null) 812 return; 813 814 818 Cookie cookie = new Cookie (Constants.LOGON_TICKET, logonTicket); 819 cookie.setMaxAge(Property.getPropertyInt(new SystemConfigKey("security.session.maxCookieAge"))); 820 cookie.setPath("/"); 821 cookie.setSecure(true); 822 response.addCookie(cookie); 823 827 Cookie cookie2 = new Cookie (Constants.DOMAIN_LOGON_TICKET, logonTicket); 828 cookie2.setMaxAge(Property.getPropertyInt(new SystemConfigKey("security.session.maxCookieAge"))); 829 cookie2.setPath("/"); 830 String host = request.getField("Host"); 833 if (host != null) { 834 HostService hostService = new HostService(host); 835 cookie2.setDomain(hostService.getHost()); 836 } 837 cookie2.setSecure(true); 838 response.addCookie(cookie2); 839 840 841 request.setAttribute("sslx.logon.cookie", new Object ()); 842 843 848 865 } 867 868 private SessionInfo addLogonTicket(HttpServletRequest request, HttpServletResponse response, User user, InetAddress address, 869 int sessionType) { 870 String logonTicket = TicketGenerator.getInstance().generateUniqueTicket("SLX"); 871 if (log.isInfoEnabled()) 872 log.info("Adding logon ticket to session " + request.getSession().getId()); 873 request.getSession().setAttribute(Constants.LOGON_TICKET, logonTicket); 874 request.setAttribute(Constants.LOGON_TICKET, logonTicket); 875 String userAgent = request.getHeader("User-Agent"); 876 SessionInfo info = SessionInfo.nextSession(request.getSession(), logonTicket, user, address, sessionType, userAgent); 877 request.getSession().setAttribute(Constants.SESSION_INFO, info); 878 try { 879 String sessionIdentifier = System.getProperty("sslexplorer.cookie", "JSESSIONID"); 880 String sessionId = null; 881 Cookie [] cookies = request.getCookies(); 882 for (int i = 0; cookies != null && i < cookies.length; i++) { 883 if (cookies[i].getName().equalsIgnoreCase(sessionIdentifier)) { 884 sessionId = cookies[i].getValue(); 885 break; 886 } 887 } 888 if (sessionId != null) { 889 logonsBySessionId.put(sessionId, info); 890 } else 891 log.warn("Could not find session id using identifier " + sessionIdentifier + " in HTTP request"); 892 } catch (Exception ex) { 893 log.warn("Failed to determine HTTP session id", ex); 894 } 895 logons.put(logonTicket, info); 896 900 Cookie cookie = new Cookie (Constants.LOGON_TICKET, logonTicket); 901 cookie.setMaxAge(Property.getPropertyInt(new SystemConfigKey("security.session.maxCookieAge"))); 902 cookie.setPath("/"); 903 cookie.setSecure(true); 904 response.addCookie(cookie); 905 909 Cookie cookie2 = new Cookie (Constants.DOMAIN_LOGON_TICKET, logonTicket); 910 cookie2.setMaxAge(Property.getPropertyInt(new SystemConfigKey("security.session.maxCookieAge"))); 911 cookie2.setPath("/"); 912 String host = request.getHeader("Host"); 915 if (host != null) { 916 HostService hostService = new HostService(host); 917 cookie2.setDomain(hostService.getHost()); 918 } 919 cookie.setSecure(true); 920 response.addCookie(cookie2); 921 return info; 922 } 923 924 public void unlockUser(String username) { 925 if (log.isInfoEnabled()) 926 log.info("Unlocking user " + username); 927 lockedUsers.remove(username); 928 } 929 930 935 public void logon(HttpServletRequest request, HttpServletResponse response, AuthenticationScheme scheme) throws Exception { 936 User user = scheme.getUser(); 937 938 String logonNotAllowedReason = LogonControllerFactory.getInstance().checkLogonAllowed(user); 940 941 if (logonNotAllowedReason != null) { 942 log.warn("Logon not allowed because '" + logonNotAllowedReason + "'"); 943 throw new Exception (logonNotAllowedReason); 944 } 945 946 if (log.isInfoEnabled()) { 947 log.info("Session logon ticket is " + (String ) request.getSession().getAttribute(Constants.LOGON_TICKET)); 948 log.info("Logging on " + scheme.getUsername() + " for scheme " + scheme.getSchemeName()); 949 } 950 unlockUser(scheme.getUsername()); 952 953 String host = (request.isSecure() || System.getProperty("jetty.force.HTTPSRedirect", "false").equals("true") ? "https" 954 : "http") + "://" 955 + request.getHeader(HttpConstants.HDR_HOST); 956 957 request.getSession().setAttribute(Constants.HOST, host); 958 SessionInfo info = null; 959 boolean fireEvent = false; 960 if (request.getSession().getAttribute(Constants.SESSION_LOCKED) == null) { 961 InetAddress address = InetAddress.getByName(request.getRemoteAddr()); 962 int sessionType = SessionInfo.getSessionTypeForUserAgent(request.getHeader("User-Agent")); 963 checkForMultipleSessions(user, address, sessionType); 964 info = addLogonTicket(request, response, user, address, sessionType); 965 try { 966 info.getHttpSession().setAttribute(Constants.VPN_AUTOSTART, 967 CoreUtil.getUsersProfileProperty(info.getHttpSession(), "client.autoStart", user)); 968 } catch (Exception e) { 969 throw new SecurityErrorException(SecurityErrorException.INTERNAL_ERROR, e.getMessage()); 970 } 971 fireEvent = true; 972 } 973 initialiseSession(request.getSession(), user); 975 CoreUtil.resetMainNavigation(request.getSession()); 977 978 char[] pw = getPasswordFromCredentials(scheme); 979 String mode = Property.getProperty(new SystemConfigKey("security.privateKeyMode")); 980 if (!mode.equals("disabled")) { 981 982 try { 983 PublicKeyStore.getInstance().verifyPrivateKey(user.getPrincipalName(), pw); 984 } catch (PromptForPasswordException e) { 985 CoreUtil.addPageInterceptListener(request.getSession(), new PromptForPrivateKeyPassphraseInterceptListener()); 986 } catch (UpdatePrivateKeyPassphraseException e) { 987 if (mode.equals("prompt")) { 988 CoreUtil.addPageInterceptListener(request.getSession(), new PromptForPrivateKeyPassphraseInterceptListener()); 989 } else { 990 CoreUtil.addPageInterceptListener(request.getSession(), new UpdatePrivateKeyPassphraseInterceptListener()); 991 } 992 } 993 } 994 995 1000 if (fireEvent) { 1001 CoreServlet.getServlet() 1002 .fireCoreEvent(new CoreEvent(this, CoreEventConstants.LOGON, scheme, info).addAttribute(CoreAttributeConstants.EVENT_ATTR_IP_ADDRESS, 1003 request.getRemoteAddr()) 1004 .addAttribute(CoreAttributeConstants.EVENT_ATTR_HOST, request.getRemoteHost()) 1005 .addAttribute(CoreAttributeConstants.EVENT_ATTR_SCHEME, scheme.getSchemeName())); 1006 } 1007 } 1008 1009 1013 public char[] getPasswordFromCredentials(AuthenticationScheme scheme) { 1014 1015 if (scheme != null) { 1016 for (Iterator i = scheme.credentials(); i.hasNext();) { 1017 Credentials cred = (Credentials) i.next(); 1018 1019 if (cred instanceof PasswordCredentials) { 1020 if (((PasswordCredentials) cred).getPassword() != null) { 1021 return ((PasswordCredentials) cred).getPassword(); 1022 } 1023 } 1024 } 1025 } 1026 return null; 1027 } 1028 1029 public SessionInfo getSessionInfo(HttpServletRequest request) { 1030 1035 1036 SessionInfo session = getSessionInfo(request.getSession()); 1037 1038 if (session == null) { 1039 Cookie [] cookies = request.getCookies(); 1040 if (cookies != null) { 1041 for (int i = 0; i < cookies.length; i++) { 1042 if (cookies[i].getName().equals(Constants.LOGON_TICKET) || cookies[i].getName() 1043 .equals(Constants.DOMAIN_LOGON_TICKET)) { 1044 session = getSessionInfo(cookies[i].getValue()); 1045 if (session != null) { 1046 request.getSession().setAttribute(Constants.LOGON_TICKET, session.getLogonTicket()); 1047 request.getSession().setAttribute(Constants.SESSION_INFO, session); 1048 break; 1049 } 1050 } 1051 } 1052 } 1053 } 1054 1055 return session; 1056 } 1057 1058 public SessionInfo getSessionInfo(HttpSession session) { 1059 String logonTicket = (String ) session.getAttribute(Constants.LOGON_TICKET); 1060 if (logonTicket != null) { 1061 return getSessionInfo(logonTicket); 1062 } 1063 return null; 1064 } 1065 1066 public SessionInfo getSessionInfoBySessionId(String sessionId) { 1067 return (SessionInfo) logonsBySessionId.get(sessionId); 1068 } 1069 1070 public SessionInfo getSessionInfo(String logonTicket) { 1071 return (SessionInfo) logons.get(logonTicket); 1072 } 1073 1074 public void attachSession(String sessionId, SessionInfo session) { 1075 logonsBySessionId.put(sessionId, session); 1076 } 1077 1078 public void registerAuthorizationTicket(String ticket, SessionInfo session) { 1079 authorizedTickets.put(ticket, session); 1080 } 1081 1082 public SessionInfo removeAuthorizationTicket(String ticket) { 1083 return (SessionInfo) authorizedTickets.remove(ticket); 1084 } 1085 1086 public SessionInfo getAuthorizationTicket(String ticket) { 1087 return (SessionInfo) authorizedTickets.get(ticket); 1088 } 1089 1090 AccountLock createLock(String username) { 1091 AccountLock lock = new AccountLock(username); 1092 lockedUsers.put(username, lock); 1093 return lock; 1094 } 1095 1096 public String checkLogonAllowed(User user) { 1097 1098 updateMostUsersEverOnline(); 1099 return null; 1100 } 1101 1102 private synchronized void moveSessionTimeoutBlocks(HttpSession oldSession, HttpSession newSession) { 1103 Map sessionTimeoutBlocks = (Map ) oldSession.getAttribute(Constants.SESSION_TIMEOUT_BLOCKS); 1104 if (sessionTimeoutBlocks != null) { 1105 newSession.setAttribute(Constants.SESSION_TIMEOUT_BLOCKS, sessionTimeoutBlocks); 1106 } 1107 Integer vpnClientSessionTimeoutBlockId = (Integer ) oldSession.getAttribute(Constants.AGENT_SESSION_TIMEOUT_BLOCK_ID); 1108 if (vpnClientSessionTimeoutBlockId != null) { 1109 newSession.setAttribute(Constants.AGENT_SESSION_TIMEOUT_BLOCK_ID, vpnClientSessionTimeoutBlockId); 1110 } 1111 newSession.setMaxInactiveInterval(sessionTimeoutBlocks == null || sessionTimeoutBlocks.size() == 0 ? oldSession.getMaxInactiveInterval() 1112 : -1); 1113 } 1114 1115 public static class UpdatePrivateKeyPassphraseInterceptListener implements PageInterceptListener { 1116 1117 public String getId() { 1118 return "updatePrivateKeyPassphrase"; 1119 } 1120 1121 public ActionForward checkForForward(Action action, ActionMapping mapping, HttpServletRequest request, 1122 HttpServletResponse response) throws PageInterceptException { 1123 if (!(action instanceof UpdatePrivateKeyPassphraseDispatchAction)) { 1124 return new ActionForward("/updatePrivateKeyPassphrase.do", true); 1125 } 1126 return null; 1127 } 1128 1129 public boolean isRedirect() { 1130 return false; 1131 } 1132 } 1133 1134 class PromptForPrivateKeyPassphraseInterceptListener implements PageInterceptListener { 1135 1136 public String getId() { 1137 return "promptForPrivateKeyPassphrase"; 1138 } 1139 1140 public ActionForward checkForForward(Action action, ActionMapping mapping, HttpServletRequest request, 1141 HttpServletResponse response) throws PageInterceptException { 1142 if (!(action instanceof PromptForPrivateKeyPassphraseDispatchAction)) { 1143 try { 1144 if ("automatic".equals(Property.getProperty(new SystemConfigKey("security.privateKeyMode")))) { 1145 return new ActionForward("/promptForPrivateKeyPassphraseAuto.do", true); 1146 } else { 1147 return new ActionForward("/promptForPrivateKeyPassphrase.do", true); 1148 } 1149 } catch (Exception e) { 1150 log.error("Failed to determine private key mode.", e); 1151 } 1152 } 1153 return null; 1154 } 1155 1156 public boolean isRedirect() { 1157 return false; 1158 } 1159 } 1160 1161 protected int getActiveSessionCount() { 1162 return getActiveSessions().size(); 1163 } 1164 1165 protected void updateMostUsersEverOnline() { 1166 1167 try { 1168 int concurrentSessions = getActiveSessionCount() + 1; 1169 if (Property.getPropertyInt(new SystemConfigKey("security.maxUserCount")) < (concurrentSessions)) { 1170 Property.setProperty(new SystemConfigKey("security.maxUserCount"), concurrentSessions, null); 1171 } 1172 } catch (Exception ex) { 1173 log.error("Could not update most users online property", ex); 1174 } 1175 } 1176 1177 class MostUsersOnline implements SystemInformationProvider { 1178 public String getBundle() { 1179 return "security"; 1180 } 1181 1182 public String getName() { 1183 return "security.maxUserCount"; 1184 } 1185 1186 public String getValue() { 1187 return String.valueOf(Property.getProperty(new SystemConfigKey("security.maxUserCount"))); 1188 } 1189 } 1190 1191 class CurrentUsersOnline implements SystemInformationProvider { 1192 public String getBundle() { 1193 return "security"; 1194 } 1195 1196 public String getName() { 1197 return "security.currentUserCount"; 1198 } 1199 1200 public String getValue() { 1201 return String.valueOf(getActiveSessionCount()); 1202 } 1203 } 1204 1205 1210 public void applyMenuItemChanges(HttpServletRequest request) { 1211 for (Iterator i = logons.entrySet().iterator(); i.hasNext();) { 1212 Map.Entry entry = (Map.Entry ) i.next(); 1213 SessionInfo sessionInfo = (SessionInfo) entry.getValue(); 1214 if (sessionInfo.getType() == SessionInfo.UI) { 1215 sessionInfo.getHttpSession().removeAttribute(Constants.MENU_TREE); 1217 String username = sessionInfo.getUser().getPrincipalName(); 1218 try { 1219 PolicyDatabaseFactory.getInstance().cleanup(); 1221 Realm realm = sessionInfo.getUser().getRealm(); 1222 sessionInfo.setUser(UserDatabaseManager.getInstance().getUserDatabase(realm).getAccount(username)); 1224 } catch (Exception e) { 1225 } 1226 } 1227 } 1228 } 1229} 1230 | Popular Tags |