All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.enterprise.admin.util.AdminCallbackHandler Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 * 
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 * 
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 * 
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright [2016-2017] [Payara Foundation and/or its affiliates]
package com.sun.enterprise.admin.util;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.IOException;
import java.net.PasswordAuthentication;
import java.security.Principal;
import java.util.Base64;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.glassfish.common.util.admin.AdminAuthenticator.AuthenticatorType;
import org.glassfish.grizzly.http.Cookie;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.api.LocalPassword;

import com.sun.enterprise.config.serverbeans.SecureAdmin;

/**
 * Handles callbacks for admin authentication other than user-provided
 * username and password, such as the local password, a limited-use token,
 * a ReST token.
 * 

* Note that some of the information the callback handler stores is really for * the use of the admin LoginModule. But because we don't control how the * login module is instantiated or initialized - but we do control that for the * callback handler - we can put that information here. This callback handler * sets the info in the callback, which is then available to the LoginModule. * * @author tjquinn */ public class AdminCallbackHandler implements CallbackHandler { public static final String COOKIE_REST_TOKEN = "gfresttoken"; public static final String HEADER_X_AUTH_TOKEN = "X-Auth-Token"; private static final Level PROGRESS_LEVEL = Level.FINE; private static final Logger LOGGER = GenericAdminAuthenticator.ADMSEC_LOGGER; private static final Base64.Decoder decoder = Base64.getMimeDecoder(); private static final String BASIC = "Basic "; private final Request request; private Map headers; private final Principal clientPrincipal; private final String originHost; private final PasswordAuthentication passwordAuthentication; private final String specialAdminIndicator; private final String token; private final String defaultAdminUsername; private final LocalPassword localPassword; private final ServiceLocator serviceLocator; public AdminCallbackHandler( final ServiceLocator serviceLocator, final Request request, final String alternateHostName, final String defaultAdminUsername, final LocalPassword localPassword) throws IOException { this.serviceLocator = serviceLocator; this.request = request; this.defaultAdminUsername = defaultAdminUsername; this.localPassword = localPassword; clientPrincipal = request.getUserPrincipal(); originHost = alternateHostName != null ? alternateHostName : request.getRemoteHost(); passwordAuthentication = basicAuth(); specialAdminIndicator = specialAdminIndicator(); token = token(); } ServiceLocator getServiceLocator() { return serviceLocator; } private static Map headers(final Request req) { final Map result = new HashMap(); for (String headerName : req.getHeaderNames()) { result.put(headerName(headerName), req.getHeader(headerName)); } return result; } private static String headerName(final String headerName) { return headerName.toLowerCase(Locale.ENGLISH); } private synchronized Map headers() { if (headers == null) { headers = headers(request); } return headers; } private String header(final String headerName) { return headers().get(headerName(headerName)); } private PasswordAuthentication basicAuth() { final String authHeader = header("Authorization"); if (authHeader == null) { LOGGER.log(PROGRESS_LEVEL, "No Authorization header found; preparing default with username {0} and empty password", defaultAdminUsername); return new PasswordAuthentication(defaultAdminUsername, new char[0]); } String dec = new String(decoder.decode(authHeader.substring(BASIC.length())), UTF_8); int i = dec.indexOf(':'); if (i < 0) { LOGGER.log(PROGRESS_LEVEL, "Authorization header contained no : to separate the username from the password; proceeding with an empty username and empty password"); return new PasswordAuthentication("", new char[0]); } final char[] password = dec.substring(i + 1).toCharArray(); String username = dec.substring(0, i); if (username.isEmpty() && ! localPassword.isLocalPassword(new String(password))) { LOGGER.log(PROGRESS_LEVEL, "Authorization header contained no username and the password is not the local password, so continue with the default username {0}", defaultAdminUsername); username = defaultAdminUsername; } LOGGER.log(PROGRESS_LEVEL, "basicAuth processing returning PasswordAuthentication with username {0}", username); return new PasswordAuthentication(username, password); } private String specialAdminIndicator() { return header(SecureAdmin.Util.ADMIN_INDICATOR_HEADER_NAME); } private String token() { return header(SecureAdmin.Util.ADMIN_ONE_TIME_AUTH_TOKEN_HEADER_NAME); } private String restToken() { final Cookie[] cookies = request.getCookies(); String result = null; if (cookies != null) { for (Cookie cookie : cookies) { if (COOKIE_REST_TOKEN.equals(cookie.getName())) { result = cookie.getValue(); } } } if (result == null) { result = request.getHeader(HEADER_X_AUTH_TOKEN); } return result; } public String getRemoteHost() { return originHost; } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback cb : callbacks) { if (cb instanceof NameCallback) { ((NameCallback) cb).setName(passwordAuthentication.getUserName()); } else if (cb instanceof PasswordCallback) { ((PasswordCallback) cb).setPassword(passwordAuthentication.getPassword()); } else if (cb instanceof TextInputCallback) { final TextInputCallback ticb = (TextInputCallback) cb; final String prompt = ticb.getPrompt(); if (AuthenticatorType.ADMIN_INDICATOR.name().equals(prompt)) { ticb.setText(specialAdminIndicator()); } else if (AuthenticatorType.ADMIN_TOKEN.name().equals(prompt)) { ticb.setText(token()); } else if (AuthenticatorType.REMOTE_HOST.name().equals(prompt)) { ticb.setText(remoteHost()); } else if (AuthenticatorType.REST_TOKEN.name().equals(prompt)) { ticb.setText(restToken()); } else if (AuthenticatorType.REMOTE_ADDR.name().equals(prompt)) { ticb.setText(remoteAddr()); } } else if (cb instanceof AdminLoginModule.PrincipalCallback) { ((AdminLoginModule.PrincipalCallback) cb).setPrincipal(clientPrincipal); } } } PasswordAuthentication pw() { return passwordAuthentication; } Principal clientPrincipal() { return clientPrincipal; } String tkn() { return token; } String remoteHost() { return originHost; } String adminIndicator() { return specialAdminIndicator; } String remoteAddr() { return request.getRemoteAddr(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy