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