001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: SSOProviderImpl.java,v 1.9 2009/02/19 05:04:01 bhavnab Exp $ 026 * 027 */ 028 029/** 030 * Portions Copyrighted 2013 ForgeRock, Inc. 031 */ 032package com.iplanet.sso.providers.dpro; 033 034import com.iplanet.am.util.SystemProperties; 035import com.iplanet.dpro.session.Session; 036import com.iplanet.dpro.session.SessionException; 037import com.iplanet.dpro.session.SessionID; 038import com.iplanet.sso.SSOException; 039import com.iplanet.sso.SSOProvider; 040import com.iplanet.sso.SSOToken; 041import com.iplanet.sso.SSOTokenID; 042import com.sun.identity.common.SearchResults; 043import com.sun.identity.shared.debug.Debug; 044import org.forgerock.openam.utils.ClientUtils; 045import java.net.InetAddress; 046import java.util.HashSet; 047import java.util.Iterator; 048import java.util.Set; 049import javax.servlet.http.HttpServletRequest; 050 051/** 052 * This <code>final</code> class <code>SSOProviderImpl</code> implements 053 * <code>SSOProvider</code> interface and provides implementation of the methods 054 * to create , destroy , check the validity of a single sign on token. 055 * 056 * @supported.api 057 */ 058public final class SSOProviderImpl implements SSOProvider { 059 060 /** Debug SSOProvider */ 061 public static Debug debug = null; 062 063 /** Check to see if the clientIPCheck is enabled */ 064 private static boolean checkIP = Boolean.valueOf( 065 SystemProperties.get("com.iplanet.am.clientIPCheckEnabled")) 066 .booleanValue(); 067 068 // Initialize debug instance; 069 static { 070 debug = Debug.getInstance("amSSOProvider"); 071 } 072 073 /** 074 * Constructs a instance of <code>SSOProviderImpl</code> 075 * 076 * @throws SSOException 077 * 078 * @supported.api 079 */ 080 public SSOProviderImpl() throws SSOException { 081 } 082 083 /** 084 * Creates a single sign on token for the <code>HttpRequest</code> 085 * 086 * @param request <code>HttpServletRequest</code> 087 * @return single sign on token for the request 088 * @exception SSOException if the single sign on token cannot be created. 089 */ 090 public SSOToken createSSOToken(HttpServletRequest request) 091 throws SSOException { 092 try { 093 SessionID sid = new SessionID(request); 094 Session session = Session.getSession(sid); 095 if (sid != null) { 096 Boolean cookieMode = sid.getCookieMode(); 097 if (debug.messageEnabled()) { 098 debug.message("cookieMode is :" + cookieMode); 099 } 100 if (cookieMode != null) { 101 session.setCookieMode(cookieMode); 102 } 103 } 104 if (checkIP && !isIPValid(session, ClientUtils.getClientIPAddress(request))) { 105 throw new Exception(SSOProviderBundle.getString("invalidIP")); 106 } 107 SSOToken ssoToken = new SSOTokenImpl(session); 108 return ssoToken; 109 } catch (Exception e) { 110 if (debug.messageEnabled()) { 111 debug.message("could not create SSOToken from HttpRequest", e); 112 } 113 throw new SSOException(e); 114 } 115 } 116 117 /** Creates a single sign on token with user or service as the entity 118 * 119 * @param user Principal representing a user or service 120 * @param password password string. 121 * @return single sign on token 122 * @exception SSOException if the single sign on token cannot be created. 123 * @exception UnsupportedOperationException Thrown to indicate that the 124 * requested operation is not supported. 125 * @deprecated This method has been deprecated. Please use the 126 * regular LDAP authentication mechanism instead. More information 127 * on how to use the authentication programming interfaces as well as the 128 * code samples can be obtained from the "Authentication 129 * Service" chapter of the OpenSSO Developer's Guide. 130 */ 131 public SSOToken createSSOToken(java.security.Principal user, 132 String password) throws SSOException, UnsupportedOperationException 133 { 134 try { 135 SSOTokenImpl ssoToken = new SSOTokenImpl(user, password); 136 if (debug.messageEnabled()) { 137 debug.message("SSO token ldap auth successful for " 138 + user.toString()); 139 } 140 return ssoToken; 141 } catch (Exception e) { 142 if (debug.messageEnabled()) { 143 debug.message("could not create SSOTOken for user " 144 + user.getName(), e); 145 } 146 throw new SSOException(e); 147 } 148 } 149 150 /** 151 * Creates a single sign on token. Note: this method should remain private 152 * and get called only by the AuthContext API. 153 * 154 * @param tokenId single sign on token ID. 155 * @param invokedByAuth boolean flag indicating that this method has 156 * been invoked by the AuthContext.getSSOToken() API. 157 * @return single sign on token. 158 * @exception SSOException if the single sign on token cannot be created. 159 * @exception UnsupportedOperationException Thrown to indicate that the 160 * requested operation is not supported. 161 */ 162 public SSOToken createSSOToken(String tokenId, boolean invokedByAuth) 163 throws SSOException, UnsupportedOperationException 164 { 165 try { 166 SessionID sessionId = new SessionID(tokenId); 167 sessionId.setComingFromAuth(invokedByAuth); 168 Session session = Session.getSession(sessionId); 169 SSOToken ssoToken = new SSOTokenImpl(session); 170 return ssoToken; 171 } catch (Exception e) { 172 if (debug.messageEnabled()) { 173 debug.message("SSOProviderImpl.createSSOToken(tokenId, boolean)" 174 +"could not create SSOTOken for token ID " + tokenId, e); 175 } 176 throw new SSOException(e); 177 } 178 } 179 180 /** 181 * Creates a single sign on token. 182 * 183 * @param tokenId single sign on token ID. 184 * @return single sign on token. 185 * @exception SSOException if the single sign on token cannot be created. 186 * @exception UnsupportedOperationException 187 * @deprecated Use #createSSOToken(String, String) 188 */ 189 public SSOToken createSSOToken(String tokenId) 190 throws SSOException, 191 UnsupportedOperationException { 192 return createSSOToken(tokenId, false); 193 } 194 195 /** 196 * Creates a single sign on token. 197 * 198 * @param tokenId 199 * single sign on token ID. 200 * @param clientIP client IP address 201 * @return single sign on token. 202 * @exception SSOException if the single sign on token cannot be created. 203 * @exception UnsupportedOperationException Thrown to indicate that the 204 * requested operation is not supported. 205 * @deprecated Use #createSSOToken(String, String) 206 */ 207 public SSOToken createSSOToken(String tokenId, String clientIP) 208 throws SSOException, UnsupportedOperationException { 209 try { 210 SessionID sessionId = new SessionID(tokenId); 211 Session session = Session.getSession(sessionId); 212 if (checkIP && !isIPValid(session, clientIP)) { 213 throw new Exception(SSOProviderBundle.getString("invalidIP")); 214 } 215 SSOToken ssoToken = new SSOTokenImpl(session); 216 return ssoToken; 217 } catch (Exception e) { 218 if (debug.messageEnabled()) { 219 debug.message("could not create SSOTOken for token ID " 220 + tokenId, e); 221 } 222 throw new SSOException(e); 223 } 224 } 225 226 /** 227 * Checks the validity of the single sign on token 228 * @param token The single sign on token object to be validated 229 * @return Returns true if the <code>SSOToken</code> is valid 230 */ 231 public boolean isValidToken(SSOToken token) { 232 /* 233 * if the token was created from createSSOToken(Principal, password) 234 * there is no association with session. Use this temp solution now. if 235 * this method is going to go away, we can remove that method. otheriwse 236 * a better mechanism has to be implemented. 237 */ 238 SSOTokenImpl tokenImpl = (SSOTokenImpl) token; 239 return (tokenImpl.isValid()); 240 } 241 242 /** 243 * Checks if the single sign on token is valid. 244 * 245 * @param token 246 * single sign on token. 247 * @exception SSOException 248 * if the single sign on token is not valid. 249 */ 250 public void validateToken(SSOToken token) throws SSOException { 251 try { 252 /* 253 * if the token was created from createSSOToken(Principal, password) 254 * there is no association with session. Use this temp solution now. 255 * if this method is going to go away, we can remove that method. 256 * otheriwse a better mechanism has to be implemented. 257 */ 258 SSOTokenImpl tokenImpl = (SSOTokenImpl) token; 259 tokenImpl.validate(); 260 } catch (Exception e) { 261 if (debug.messageEnabled()) { 262 debug.message("validateToken: ", e); 263 } 264 throw new SSOException(SSOProviderBundle.rbName, "invalidtoken", 265 null); 266 } 267 } 268 269 /** Destroys a single sign on token 270 * 271 * @param token The single sign on token object to be destroyed 272 * @throws SSOException if the given token cannot be destroyed 273 */ 274 public void destroyToken(SSOToken token) throws SSOException { 275 try { 276 SSOTokenImpl tokenImpl = (SSOTokenImpl) token; 277 if (tokenImpl.isLdapConnection() == true) { 278 tokenImpl.setStatus(false); 279 return; 280 } 281 SSOTokenID tokenid = token.getTokenID(); 282 String id = tokenid.toString(); 283 SessionID sessid = new SessionID(id); 284 Session session = Session.getSession(sessid); 285 session.destroySession(session); 286 } catch (Exception e) { 287 if (debug.messageEnabled()) { 288 debug.message("DestroyToken: ", e); 289 } 290 throw new SSOException(e); 291 } 292 } 293 294 /** 295 * Validate the IP address of the client with the IP stored in Session. 296 * @param sess Session object associated with the token 297 * @param clientIP IP address of the current client who made 298 * <code>HttpRequest</code>. 299 * @return Returns true if the IP is valid else false. 300 * @throws SSOException if IP cannot be validated for the given session 301 */ 302 public boolean isIPValid(Session sess, String clientIP) throws SSOException 303 { 304 boolean check = false; 305 try { 306 InetAddress sessIPAddress = InetAddress.getByName(sess 307 .getProperty("Host")); 308 InetAddress clientIPAddress = InetAddress.getByName(clientIP); 309 if (sessIPAddress.equals(clientIPAddress)) { 310 check = true; 311 } 312 } catch (Exception e) { 313 if (debug.messageEnabled()) { 314 debug.message("IP address check of Token Failed", e); 315 } 316 } 317 return check; 318 } 319 320 /** 321 * Refresh the Session corresponding to the single sign on token from the 322 * Session Server. 323 * @param token single sign on token for which session need to be refreshed 324 * @throws SSOException if the session cannot be refreshed 325 * 326 */ 327 public void refreshSession(SSOToken token) throws SSOException { 328 try { 329 SSOTokenID tokenId = token.getTokenID(); 330 SessionID sid = new SessionID(tokenId.toString()); 331 Session session = Session.getSession(sid); 332 session.refresh(true); 333 } catch (Exception e) { 334 debug.error("Error in refreshing the session from sessions erver"); 335 throw new SSOException(e); 336 } 337 } 338 339 /** 340 * Destroys a single sign on token. 341 * 342 * @param destroyer 343 * The single sign on token object used to authorize the 344 * operation 345 * @param destroyed 346 * The single sign on token object to be destroyed. 347 * @throws SSOException 348 * if the there was an error during communication with session 349 * service. 350 * 351 * @supported.api 352 */ 353 public void destroyToken(SSOToken destroyer, SSOToken destroyed) 354 throws SSOException { 355 try { 356 Session requester = ((SSOTokenImpl) destroyer).getSession(); 357 Session target = ((SSOTokenImpl) destroyed).getSession(); 358 requester.destroySession(target); 359 } catch (SessionException e) { 360 throw new SSOException(e); 361 } 362 } 363 364 /** 365 * Returns a list of single sign on token objects 366 * which correspond to valid Sessions accessible to requester. single sign 367 * on token objects returned are restricted: they can only be used to 368 * retrieve properties and destroy sessions they represent. 369 * 370 * @param requester 371 * The single sign on token object used to authorize the 372 * operation 373 * @param server 374 * The server for which the valid sessions are to be retrieved 375 * @return Set of Valid Sessions 376 * @throws SSOException 377 * if the there was an error during communication with session 378 * service. 379 * 380 * @supported.api 381 */ 382 public Set getValidSessions(SSOToken requester, String server) 383 throws SSOException { 384 Set results = new HashSet(); 385 try { 386 387 SearchResults result = ((SSOTokenImpl) requester).getSession() 388 .getValidSessions(server, null); 389 390 for (Iterator iter = result.getResultAttributes().values() 391 .iterator(); iter.hasNext();) { 392 Session s = (Session) iter.next(); 393 if (s != null) { 394 results.add(new SSOTokenImpl(s)); 395 } 396 } 397 } catch (SessionException e) { 398 throw new SSOException(e); 399 } 400 return results; 401 } 402}