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: AdminTokenAction.java,v 1.14 2009/06/19 02:35:11 bigfatrat Exp $ 026 * 027 */ 028 029/* 030 * Portions Copyrighted 2010-2014 ForgeRock AS 031 */ 032package com.sun.identity.security; 033 034import com.iplanet.am.util.AdminUtils; 035import com.iplanet.am.util.SystemProperties; 036import com.iplanet.services.util.Crypt; 037import com.iplanet.sso.SSOException; 038import com.iplanet.sso.SSOToken; 039import com.iplanet.sso.SSOTokenManager; 040import com.sun.identity.authentication.internal.AuthContext; 041import com.sun.identity.authentication.internal.AuthPrincipal; 042import com.sun.identity.shared.debug.Debug; 043import java.security.PrivilegedAction; 044import org.forgerock.util.thread.listener.ShutdownListener; 045 046/** 047 * The class is used to perform privileged operations using 048 * <code>java.security.AccessController.doPrivileged() 049 * </code> when trying to 050 * get Application single sign on token. There are four approaches to get single 051 * sign on token. 1. Return the single sign on token of the administrator 052 * configured in <code>serverconfig.xml</code> if the code runs on server 053 * site. 2. If #1 fails, it implies the client is using remote SDK. If 054 * <code>com.sun.identity.security.AdminToken</code> is specified in 055 * <code>AMConfig.properties</code>, we will call this application token 056 * provider plug-in to retrieve the single sign on token. 3. If #2 fails, we 057 * look for <code>com.sun.identity.agents.app.username</code> and 058 * <code>com.iplanet.am.service.password</code> in 059 * <code>AMConfig.properties</code>, if so, we will generate single sign 060 * token of administrator based on the user name and password. 4. If #3 fails, 061 * we look for <code>com.sun.identity.agents.app.username</code> and 062 * <code>com.iplanet.am.service.secret</code> in 063 * <code>AMConfig.properties</code>. If so, we will generate single sign on 064 * token based on the user name and secret. 065 * 066 * Note: Java security permissions check for OpenSSO can be enabled 067 * by setting the property <code>com.sun.identity.security.checkcaller</code> to 068 * true in <code>AMConfig.properties</code> file. 069 * 070 * </PRE> 071 * 072 * @supported.all.api 073 */ 074public class AdminTokenAction implements PrivilegedAction<SSOToken> { 075 076 private static SSOTokenManager tokenManager; 077 078 private static SSOToken appSSOToken; 079 080 private static SSOToken internalAppSSOToken; 081 082 private static AdminTokenAction instance; 083 084 private static boolean authInitialized; 085 086 static Debug debug = Debug.getInstance("amSecurity"); 087 088 static final String ADMIN_TOKEN_PROVIDER = 089 "com.sun.identity.security.AdminToken"; 090 091 static final String APP_USERNAME = 092 "com.sun.identity.agents.app.username"; 093 094 static final String APP_SECRET = 095 "com.iplanet.am.service.secret"; 096 097 static final String APP_PASSWORD = 098 "com.iplanet.am.service.password"; 099 100 public static final String AMADMIN_MODE = 101 "com.sun.identity.security.amadmin"; 102 103 //OPENAM-1109 admin token doesn't get cleared 104 //because SSOTokenManager#isValidToken() doesn't get 105 //real session status. This flag makes AdminTokenAction 106 //to refresh session status and get the true status. 107 public static final String VALIDATE_SESSION = 108 "openam.identity.security.validateSession"; 109 110 private static boolean validateSession; 111 112 /** 113 * Returns a cached instance <code>AdminTokenAction</code>. 114 * 115 * @return instance of <code>AdminTokenAction</code>. 116 */ 117 public static AdminTokenAction getInstance() { 118 if (instance == null) { 119 instance = new AdminTokenAction(); 120 } 121 return instance; 122 } 123 124 /** 125 * Default constructor 126 */ 127 public AdminTokenAction() { 128 if (tokenManager == null) { 129 try { 130 tokenManager = SSOTokenManager.getInstance(); 131 com.sun.identity.common.ShutdownManager.getInstance().addApplicationSSOTokenDestroyer( 132 new ShutdownListener() { 133 public void shutdown() { 134 AdminTokenAction.reset(); 135 } 136 }); 137 } catch (SSOException ssoe) { 138 debug.error("AdminTokenAction::init Unable to get " + 139 "SSOTokenManager", ssoe); 140 } 141 } 142 validateSession = SystemProperties.getAsBoolean(VALIDATE_SESSION); 143 } 144 145 /** 146 * Informs AdminTokenAction that Authentication has been initialized 147 * This class will start using Authentication service to obtain 148 * SSOToken for admin users 149 */ 150 public void authenticationInitialized() { 151 authInitialized = true; 152 // Generate the DPro's SSOToken 153 appSSOToken = getSSOToken(); 154 if (debug.messageEnabled()) { 155 debug.message("AdminTokenAction:authenticationInit " + 156 "called. AppSSOToken className=" + (String) 157 ((appSSOToken == null) ? "null" : 158 appSSOToken.getClass().getName())); 159 } 160 // Clear internalAppSSOToken 161 internalAppSSOToken = null; 162 } 163 164 /** 165 * Resets cached SSOToken. WITHOUT destroying. Called when we know the 166 * token is invalid 167 */ 168 public static void invalid() { 169 appSSOToken = null; 170 171 if (debug.messageEnabled()) { 172 debug.message("AdminTokenAction:invalid called"); 173 } 174 } 175 176 /** 177 * Resets cached SSOToken. 178 */ 179 public static void reset() { 180 if (appSSOToken != null) { 181 if (tokenManager != null) { 182 try { 183 tokenManager.destroyToken(appSSOToken); 184 } catch (SSOException ssoe) { 185 debug.error( 186 "AdminTokenAction.reset: cannot destroy appSSOToken.", 187 ssoe); 188 } 189 } 190 191 appSSOToken = null; 192 } 193 internalAppSSOToken = null; 194 } 195 196 /* (non-Javadoc) 197 * @see java.security.PrivilegedAction#run() 198 */ 199 public SSOToken run() { 200 // Check if we have a valid cached SSOToken 201 if ((appSSOToken != null) && tokenManager.isValidToken(appSSOToken)) { 202 try { 203 if (validateSession) { 204 tokenManager.refreshSession(appSSOToken); 205 } 206 if (tokenManager.isValidToken(appSSOToken)) { 207 return (appSSOToken); 208 } 209 } catch (SSOException ssoe) { 210 debug.error( 211 "AdminTokenAction.reset: couldn't retrieve valid token.", 212 ssoe); 213 } 214 } 215 216 // Check if internalAppSSOToken is present 217 if ((internalAppSSOToken != null) && 218 tokenManager.isValidToken(internalAppSSOToken)) { 219 return (internalAppSSOToken); 220 } 221 222 // Try getting the token from serverconfig.xml 223 SSOToken answer = getSSOToken(); 224 if (answer != null) { 225 if (!SystemProperties.isServerMode() || authInitialized) { 226 appSSOToken = answer; 227 } 228 return answer; 229 } else if (debug.messageEnabled()) { 230 debug.message("AdminTokenAction::run Unable to get SSOToken " + 231 " from serverconfig.xml"); 232 } 233 234 // Check for configured Application Token Provider 235 // in AMConfig.properties 236 String appTokenProviderName = SystemProperties.get( 237 ADMIN_TOKEN_PROVIDER); 238 if (appTokenProviderName != null) { 239 try { 240 AppSSOTokenProvider appSSOTokenProvider = 241 (AppSSOTokenProvider) Class. 242 forName(appTokenProviderName).newInstance(); 243 244 answer = appSSOTokenProvider.getAppSSOToken(); 245 } catch (Throwable ce) { 246 if (debug.warningEnabled()) { 247 debug.warning("AdminTokenAction: Exception " + 248 "while calling appSSOToken provider plugin.", ce); 249 } 250 } 251 } else { 252 String appUserName = SystemProperties.get(APP_USERNAME); 253 String tmp = SystemProperties.get(APP_SECRET); 254 String passwd = SystemProperties.get(APP_PASSWORD); 255 String appPassword = null; 256 257 if (passwd != null && passwd.length() != 0) { 258 appPassword = passwd; 259 } else if (tmp != null && tmp.length() != 0) { 260 try { 261 appPassword = Crypt.decode(tmp); 262 } catch (Throwable t) { 263 if (debug.messageEnabled()) { 264 debug.message("AdminTokenAction::run Unable to " + 265 " decrypt secret password", t); 266 } 267 } 268 } 269 270 if ((appUserName == null) || (appUserName.length() == 0) || 271 (appPassword == null) || (appPassword.length() == 0)) { 272 debug.message( 273 "AdminTokenAction: App user name or password is empty"); 274 } else { 275 if (AdminTokenAction.debug.messageEnabled()) { 276 debug.message("App user name: " + appUserName); 277 } 278 SystemAppTokenProvider tokenProd = 279 new SystemAppTokenProvider(appUserName, appPassword); 280 answer = tokenProd.getAppSSOToken(); 281 } 282 } 283 284 // If SSOToken is NULL, AM would not bootstrap: fatal error 285 if (answer == null) { 286 debug.error("AdminTokenAction: FATAL ERROR: " + 287 "Cannot obtain Application SSO token." + 288 "\nCheck AMConfig.properties for the following properties" + 289 "\n\tcom.sun.identity.agents.app.username" + 290 "\n\tcom.iplanet.am.service.password"); 291 throw new AMSecurityPropertiesException("AdminTokenAction: " + 292 " FATAL ERROR: Cannot obtain Application SSO token." + 293 "\nCheck AMConfig.properties for the following properties" + 294 "\n\tcom.sun.identity.agents.app.username" + 295 "\n\tcom.iplanet.am.service.password"); 296 } else if (!SystemProperties.isServerMode() || authInitialized) { 297 // Cache the SSOToken if not in server mode (i.e., in the 298 // case of client sdk) or if the authN has been initialized 299 appSSOToken = answer; 300 } 301 return answer; 302 } 303 304 private static SSOToken getSSOToken() { 305 // Please NEVER make this method public!!!!!!!!!! 306 // This can only be used in server site. 307 SSOToken ssoAuthToken = null; 308 309 try { 310 //call method directly 311 if (AdminUtils.getAdminPassword() != null) { 312 String adminDN = AdminUtils.getAdminDN(); 313 String adminPassword = new String(AdminUtils.getAdminPassword()); 314 if (!authInitialized && (SystemProperties.isServerMode() || 315 SystemProperties.get(AMADMIN_MODE) != null)) { 316 // Use internal auth context to get the SSOToken 317 AuthContext ac = new AuthContext(new AuthPrincipal(adminDN), 318 adminPassword.toCharArray()); 319 internalAppSSOToken = ssoAuthToken = ac.getSSOToken(); 320 } else { 321 // Copy the authentication state 322 boolean authInit = authInitialized; 323 if (authInit) { 324 authInitialized = false; 325 } 326 327 // Obtain SSOToken using AuthN service 328 ssoAuthToken = (new SystemAppTokenProvider(adminDN, 329 adminPassword)).getAppSSOToken(); 330 331 // Restore the authentication state 332 if (authInit && ssoAuthToken != null) { 333 authInitialized = true; 334 } 335 } 336 } 337 } catch (NoClassDefFoundError ne) { 338 if (debug.messageEnabled()) { 339 debug.message("AdminTokenAction::getSSOToken " + 340 "Not found AdminDN and AdminPassword.", ne); 341 } 342 } catch (Throwable t) { 343 if (debug.messageEnabled()) { 344 debug.message("AdminTokenAction::getSSOToken " + 345 "Exception reading from serverconfig.xml", t); 346 } 347 } 348 return ssoAuthToken; 349 } 350}
Copyright © 2010-2017, ForgeRock All Rights Reserved.