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

com.sun.jmx.remote.opt.security.SASLServerHandler Maven / Gradle / Ivy

/*
 * @(#)file      SASLServerHandler.java
 * @(#)author    Sun Microsystems, Inc.
 * @(#)version   1.24
 * @(#)lastedit  07/03/08
 * @(#)build     @BUILD_TAG_PLACEHOLDER@
 *
 * 
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright (c) 2007 Sun Microsystems, Inc. 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 http://opendmk.dev.java.net/legal_notices/licenses.txt or in the 
 * LEGAL_NOTICES folder that accompanied this code. 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 found at
 *     http://opendmk.dev.java.net/legal_notices/licenses.txt
 * or in the LEGAL_NOTICES folder that accompanied this code.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.
 * 
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * 
 *       "Portions Copyrighted [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 or 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.
 * 
 */ 

package com.sun.jmx.remote.opt.security;

import java.io.IOException;
import java.net.Socket;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.Map;

import javax.management.remote.JMXPrincipal;
import javax.management.remote.generic.MessageConnection;
import javax.management.remote.message.ProfileMessage;
import javax.management.remote.message.SASLMessage;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslServer;

import com.sun.jmx.remote.generic.ProfileServer;
import com.sun.jmx.remote.opt.util.ClassLogger;
import com.sun.jmx.remote.socket.SocketConnectionIf;

/**
 * This class implements the server side SASL profile.
 */
public class SASLServerHandler implements ProfileServer {

    //-------------
    // Constructors
    //-------------

    public SASLServerHandler(String profile, Map env) {
        this.profile = profile;
        this.env = env;
    }

    //---------------------------------------
    // ProfileServer interface implementation
    //---------------------------------------

    public void initialize(MessageConnection mc, Subject s) throws IOException {

        this.mc = mc;
	this.subject = s;

        // Check if instance of SocketConnectionIf
        // and retrieve underlying socket
        //
        if (mc instanceof SocketConnectionIf) {
            socket = ((SocketConnectionIf)mc).getSocket();
        } else {
            throw new IOException("Not an instance of SocketConnectionIf");
        }

        // Prepare parameters for creating SASL server
        //
	mechanism = profile.substring(profile.indexOf("SASL/") + 5);
        String server = (String) env.get("jmx.remote.x.sasl.server.name");
        if (server == null)
            server = socket.getLocalAddress().getHostName();
        CallbackHandler cbh =
            (CallbackHandler) env.get("jmx.remote.sasl.callback.handler");

	// Create SASL server to use using SASL package
	//
	saslServer = Sasl.createSaslServer(mechanism, "jmxmp",
					   server, env, cbh);
	if (saslServer == null) {
	    final String detail =
		"Unable to create SASL server connection for " +
		"authentication mechanism [" + mechanism + "]";
	    throw new IOException(detail);
	}
    }

    public ProfileMessage produceMessage() throws IOException {
	int status;
	if (saslServer.isComplete()) {
	    status = SASLMessage.COMPLETE;
	} else {
	    status = SASLMessage.CONTINUE;
	}
	SASLMessage challenge = new SASLMessage(mechanism, status, blob);
	if (logger.traceOn()) {
	    logger.trace("produceMessage",
			 ">>>>> SASL server message <<<<<");
	    logger.trace("produceMessage",
			 "Profile Name : " + challenge.getProfileName());
	    logger.trace("produceMessage",
			 "Status : " + challenge.getStatus());
	}
        return challenge;
    }

    public void consumeMessage(ProfileMessage pm) throws IOException {
        if (!(pm instanceof SASLMessage)) {
            throw new IOException("Unexpected profile message type: " +
                                  pm.getClass().getName());
        }
        SASLMessage response = (SASLMessage) pm;
	if (logger.traceOn()) {
	    logger.trace("consumeMessage",
			 ">>>>> SASL client message <<<<<");
	    logger.trace("consumeMessage",
			 "Profile Name : " + response.getProfileName());
	    logger.trace("consumeMessage",
			 "Status : " + response.getStatus());
	}
        if (response.getStatus() != SASLMessage.CONTINUE) {
            throw new IOException("Unexpected SASL status [" +
                                  response.getStatus() + "]");
        }
	if (!saslServer.isComplete()) {
	    blob = saslServer.evaluateResponse(response.getBlob());
	} else {
	    throw new IOException("SASL authentication complete despite " +
				  "the client claim for non-completion");
	}
    }

    public boolean isComplete() {
	return saslServer.isComplete();
    }

    public Subject activate() throws IOException {
	// If negotiated integrity or privacy
	//
	String qop = (String) saslServer.getNegotiatedProperty(Sasl.QOP);
	if (qop != null &&
	    (qop.equalsIgnoreCase("auth-int") ||
	     qop.equalsIgnoreCase("auth-conf"))) {
	    // Replace the current input/output streams in
	    // MessageConnection by the SASL input/output streams
	    //
	    SASLInputStream saslis =
		new SASLInputStream(saslServer, socket.getInputStream());
	    SASLOutputStream saslos =
		new SASLOutputStream(saslServer, socket.getOutputStream());
	    ((SocketConnectionIf)mc).replaceStreams(saslis, saslos);
	}
	// Retrieve authorization id
	//
	final String authorizationId = saslServer.getAuthorizationID();
	final Principal principal = new JMXPrincipal(authorizationId);
	if (subject == null) subject = new Subject();
	AccessController.doPrivileged(new PrivilegedAction() {
		public Object run() {
		    subject.getPrincipals().add(principal);
		    return null;
		}
	    });
	return subject;
    }

    public void terminate() throws IOException {
        saslServer.dispose();
    }

    public String getName() {
	return profile;
    }

    //--------------------
    // Protected variables
    //--------------------

    private SaslServer saslServer = null;

    //------------------
    // Private variables
    //------------------

    private byte[] blob = null;
    private Map env = null;
    private MessageConnection mc = null;
    private Socket socket = null;
    private String mechanism = null;
    private String profile = null;
    private Subject subject = null;
    private static final ClassLogger logger =
	new ClassLogger("javax.management.remote.misc", "SASLServerHandler");
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy