0N/A/*
2362N/A * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
0N/A * @bug 5014493
0N/A * @summary SaslServer.wrap throws NullPointerException when security
0N/A * layer negotiated
0N/A * @ignore see run-conf-wjaas.csh for instructions for how to run this test
0N/A */
0N/A/*
0N/A * Can set logging to FINEST to view exchange.
0N/A */
0N/Aimport javax.security.sasl.*;
0N/Aimport javax.security.auth.callback.*;
0N/Aimport java.security.*;
0N/Aimport javax.security.auth.Subject;
0N/Aimport javax.security.auth.login.*;
0N/Aimport com.sun.security.auth.callback.*;
0N/Aimport java.util.HashMap;
0N/A
0N/Apublic class ConfSecurityLayer {
0N/A private static final String MECH = "GSSAPI";
0N/A private static final String SERVER_FQDN = "machineX.imc.org";
0N/A private static final String PROTOCOL = "sample";
0N/A
0N/A private static String namesfile, proxyfile;
0N/A private static final byte[] EMPTY = new byte[0];
0N/A private static boolean auto;
0N/A private static boolean verbose = false;
0N/A
0N/A public static void main(String[] args) throws Exception {
0N/A if (args.length == 0) {
0N/A namesfile = null;
0N/A auto = true;
0N/A } else {
0N/A int i = 0;
0N/A if (args[i].equals("-m")) {
0N/A i++;
0N/A auto = false;
0N/A }
0N/A if (args.length > i) {
0N/A namesfile = args[i++];
0N/A if (args.length > i) {
0N/A proxyfile = args[i];
0N/A }
0N/A } else {
0N/A namesfile = null;
0N/A }
0N/A }
0N/A
0N/A CallbackHandler clntCbh = null;
0N/A final CallbackHandler srvCbh = new PropertiesFileCallbackHandler(
0N/A null, namesfile, proxyfile);
0N/A
0N/A Subject clntSubj = doLogin("client");
0N/A Subject srvSubj = doLogin("server");
0N/A final HashMap clntprops = new HashMap();
0N/A final HashMap srvprops = new HashMap();
0N/A
0N/A clntprops.put(Sasl.QOP, "auth-conf");
0N/A srvprops.put(Sasl.QOP, "auth,auth-int,auth-conf");
0N/A
0N/A final SaslClient clnt = (SaslClient)
0N/A Subject.doAs(clntSubj, new PrivilegedExceptionAction() {
0N/A public Object run() throws Exception {
0N/A return Sasl.createSaslClient(
0N/A new String[]{MECH}, null, PROTOCOL, SERVER_FQDN,
0N/A clntprops, null);
0N/A }
0N/A });
0N/A
0N/A if (verbose) {
0N/A System.out.println(clntSubj);
0N/A System.out.println(srvSubj);
0N/A }
0N/A final SaslServer srv = (SaslServer)
0N/A Subject.doAs(srvSubj, new PrivilegedExceptionAction() {
0N/A public Object run() throws Exception {
0N/A return Sasl.createSaslServer(MECH, PROTOCOL, SERVER_FQDN,
0N/A srvprops, srvCbh);
0N/A }
0N/A });
0N/A
0N/A
0N/A if (clnt == null) {
0N/A throw new IllegalStateException(
0N/A "Unable to find client impl for " + MECH);
0N/A }
0N/A if (srv == null) {
0N/A throw new IllegalStateException(
0N/A "Unable to find server impl for " + MECH);
0N/A }
0N/A
0N/A byte[] response;
0N/A byte[] challenge;
0N/A
0N/A response = (byte[]) Subject.doAs(clntSubj,
0N/A new PrivilegedExceptionAction() {
0N/A public Object run() throws Exception {
0N/A return (clnt.hasInitialResponse()? clnt.evaluateChallenge(EMPTY) : EMPTY);
0N/A }});
0N/A
0N/A while (!clnt.isComplete() || !srv.isComplete()) {
0N/A final byte[] responseCopy = response;
0N/A challenge = (byte[]) Subject.doAs(srvSubj,
0N/A new PrivilegedExceptionAction() {
0N/A public Object run() throws Exception {
0N/A return srv.evaluateResponse(responseCopy);
0N/A }});
0N/A
0N/A if (challenge != null) {
0N/A final byte[] challengeCopy = challenge;
0N/A response = (byte[]) Subject.doAs(clntSubj,
0N/A new PrivilegedExceptionAction() {
0N/A public Object run() throws Exception {
0N/A return clnt.evaluateChallenge(challengeCopy);
0N/A }});
0N/A }
0N/A }
0N/A
0N/A if (clnt.isComplete() && srv.isComplete()) {
0N/A if (verbose) {
0N/A System.out.println("SUCCESS");
0N/A System.out.println("authzid is " + srv.getAuthorizationID());
0N/A }
0N/A } else {
0N/A throw new IllegalStateException("FAILURE: mismatched state:" +
0N/A " client complete? " + clnt.isComplete() +
0N/A " server complete? " + srv.isComplete());
0N/A }
0N/A
0N/A if (verbose) {
0N/A System.out.println(clnt.getNegotiatedProperty(Sasl.QOP));
0N/A }
0N/A
0N/A // Now try to use security layer
0N/A
0N/A byte[] clntBuf = new byte[]{0, 1, 2, 3};
0N/A byte[] wrappedClnt = clnt.wrap(clntBuf, 0, clntBuf.length);
0N/A System.out.println("plaintext2: " + bytesToString(clntBuf));
0N/A System.out.println("wrapped2: " + bytesToString(wrappedClnt));
0N/A
0N/A byte[] srvBuf = new byte[]{10, 11, 12, 13};
0N/A byte[] wrappedSrv = srv.wrap(srvBuf, 0, srvBuf.length);
0N/A System.out.println("plaintext1: " + bytesToString(srvBuf));
0N/A System.out.println("wrapped1: " + bytesToString(wrappedSrv));
0N/A
0N/A byte[] unwrapped1 = clnt.unwrap(wrappedSrv, 0, wrappedSrv.length);
0N/A System.out.println("unwrapped1: " + bytesToString(unwrapped1));
0N/A
0N/A byte[] unwrapped2 = srv.unwrap(wrappedClnt, 0, wrappedClnt.length);
0N/A System.out.println("unwrapped2: " + bytesToString(unwrapped2));
0N/A }
0N/A
0N/A private static Subject doLogin(String msg) throws LoginException {
0N/A LoginContext lc = null;
0N/A if (verbose) {
0N/A System.out.println(msg);
0N/A }
0N/A try {
0N/A lc = new LoginContext(msg, new TextCallbackHandler());
0N/A
0N/A // Attempt authentication
0N/A // You might want to do this in a "for" loop to give
0N/A // user more than one chance to enter correct username/password
0N/A lc.login();
0N/A
0N/A } catch (LoginException le) {
0N/A throw le;
0N/A }
0N/A return lc.getSubject();
0N/A }
0N/A
0N/A private static String bytesToString(byte[] digest) {
0N/A // Get character representation of digest
0N/A StringBuffer digestString = new StringBuffer();
0N/A
0N/A for (int i = 0; i < digest.length; i++) {
0N/A if ((digest[i] & 0x000000ff) < 0x10) {
0N/A digestString.append("0" +
0N/A Integer.toHexString(digest[i] & 0x000000ff));
0N/A } else {
0N/A digestString.append(
0N/A Integer.toHexString(digest[i] & 0x000000ff));
0N/A }
0N/A }
0N/A return digestString.toString();
0N/A }
0N/A}