Package com.sun.jdmk.security.sasl.plain

Source Code of com.sun.jdmk.security.sasl.plain.PlainServer

/*
* @(#)file      PlainServer.java
* @(#)author    Sun Microsystems, Inc.
* @(#)version   1.4
* @(#)date      07/10/01
*
*
* 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.jdmk.security.sasl.plain;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.Sasl;
import javax.security.sasl.AuthenticationException;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;

import com.sun.jdmk.security.sasl.AuthenticateCallback;

/**
* Implements the PLAIN SASL server mechanism.
* (<A HREF="http://ftp.isi.edu/in-notes/rfc2595.txt">RFC 2595</A>)
* <p>
* Requires the following callbacks to be satisfied by the callback handler
* when using PLAIN:
* <ul>
*   <li>AuthenticateCallback: to verify the authentication identity and
*       password with the system authentication database.</li>
*   <li>AuthorizeCallback: to verify that the authentication credentials
*       permit the client to log in as the authorization identity.</li>
* </ul>
*/
final class PlainServer implements SaslServer {

    public PlainServer(CallbackHandler cbh) {
  this.cbh = cbh;
    }

    public String getMechanismName() {
  return "PLAIN";
    }

    public byte[] evaluateResponse(byte[] response) throws SaslException {
  if (completed) {
      throw new IllegalStateException(
          "PLAIN authentication already completed");
  }
  completed = true;

  // Extract authorization_id/authentication_id/password from response
  //
  int indexSeparator1 = -1;
  int indexSeparator2 = -1;
  for (int i = 0; i < response.length; i++) {
      if (response[i] != SEPARATOR) {
    continue;
      } else {
    if (indexSeparator1 == -1) {
        indexSeparator1 = i;
    } else if (indexSeparator2 == -1) {
        indexSeparator2 = i;
    }
      }
  }
        if ((indexSeparator1 < 0) ||
            (indexSeparator2 < 0) ||
            (indexSeparator1 + 1 == indexSeparator2) ||
            (indexSeparator2 + 1 == response.length))
            throw new IllegalStateException("PLAIN authentication error: " +
                                            "Response format should be: " +
                                            "[authorization_id]" +
                                            "<US-ASCII NUL>" +
                                            "authentication_id" +
                                            "<US-ASCII NUL>" +
                                            "password.");
  int authzidSize = indexSeparator1;
  int authnidSize = indexSeparator2 - indexSeparator1 - 1;
  int passwdSize = response.length - indexSeparator2 - 1;
  byte authzid[] = new byte[authzidSize];
  byte authnid[] = new byte[authnidSize];
  byte passwd[] = new byte[passwdSize];
  System.arraycopy(response, 0, authzid, 0, authzidSize);
  System.arraycopy(response, indexSeparator1+1, authnid, 0, authnidSize);
  System.arraycopy(response, indexSeparator2+1, passwd, 0, passwdSize);
  String authenticationID;
  String authorizationID;
  String password;
  try {
      authenticationID = new String(authnid, "UTF-8");
      password = new String(passwd, "UTF-8");
      for (int i = 0; i < passwd.length; i++)
    passwd[i] = 0;
      passwd = null;
      if (authzid.length == 0)
    authorizationID = authenticationID;
      else
    authorizationID = new String(authzid, "UTF-8");
  } catch (UnsupportedEncodingException e) {
      throw new SaslException("PLAIN: Cannot get UTF-8 encoding of ids",
            e);
  }

  // Let the callback handler verify the remote authentication identity
  // and password with the system authentication database.
  //
  verifyAuthenticationCredentials(authenticationID, password);

  // Let the callback handler verify that the authentication credentials
  // permit the client to log in as the authorization identity.
  //
  verifyAuthorizationID(authenticationID, authorizationID);

  return null;
    }

    public String getAuthorizationID() {
  return authorizationID;
    }

    public boolean isComplete() {
  return completed;
    }

    public byte[] unwrap(byte[] incoming, int offset, int len)
  throws SaslException {
  if (completed) {
      throw new SaslException(
        "PLAIN supports neither integrity nor privacy");
  } else {
      throw new IllegalStateException(
          "PLAIN authentication not completed");
  }
    }

    public byte[] wrap(byte[] outgoing, int offset, int len)
        throws SaslException {
  if (completed) {
      throw new SaslException(
        "PLAIN supports neither integrity nor privacy");
  } else {
      throw new IllegalStateException(
          "PLAIN authentication not completed");
  }
    }

    public Object getNegotiatedProperty(String propName) {
        if (completed) {
            if (propName.equals(Sasl.QOP)) {
                return "auth";
            } else {
                return null;
            }
        } else {
      throw new IllegalStateException(
          "PLAIN authentication not completed");
        }
    }

    public void dispose() throws SaslException {
    }

    private void verifyAuthenticationCredentials(String username,
             String password)
  throws SaslException {
  final String msg =
      "PLAIN: Authentication credentials verification failed!";
  char passwd[] = password.toCharArray();
  AuthenticateCallback authnCb =
      new AuthenticateCallback(username, passwd);
  for (int i = 0; i < passwd.length; i++)
      passwd[i] = ' ';
  passwd = null;
  try {
      cbh.handle(new Callback[] { authnCb });
        } catch (IOException e) {
            throw new SaslException(msg, e);
        } catch (UnsupportedCallbackException e) {
            throw new SaslException(msg, e);
        }
  authnCb.clearPassword();
  if (!authnCb.isAuthenticated()) {
            throw new AuthenticationException(msg);
  }
    }

    private void verifyAuthorizationID(String authenticationID,
               String authorizationID)
  throws SaslException {
  final String msg = "PLAIN: AuthorizationID verification failed!";
  AuthorizeCallback authzCb =
      new AuthorizeCallback(authenticationID, authorizationID);
  try {
      cbh.handle(new Callback[] { authzCb });
        } catch (IOException e) {
            throw new SaslException(msg, e);
        } catch (UnsupportedCallbackException e) {
            throw new SaslException(msg, e);
        }
  if (authzCb.isAuthorized()) {
      this.authorizationID = authzCb.getAuthorizedID();
  } else {
            throw new SaslException("PLAIN: " +
            authenticationID +
            " is not authorized to act as " +
            authorizationID);
  }
    }

    private boolean completed;
    private CallbackHandler cbh;
    private String authorizationID;
    private static final byte SEPARATOR = 0; // US-ASCII <NUL>
}
TOP

Related Classes of com.sun.jdmk.security.sasl.plain.PlainServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.