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.