AuthOnly.java revision 0:37a05a11f281
1/*
2 * Copyright 2003 Sun Microsystems, Inc.  All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 4634892
27 * @summary Ensure authentication via GSS-API/Kerberos v5 works.
28 * @ignore see runwjaas.csh for instructions for how to run this test
29 */
30/*
31 * Can set logging to FINEST to view exchange.
32 */
33import javax.security.sasl.*;
34import javax.security.auth.callback.*;
35import java.security.*;
36import javax.security.auth.Subject;
37import javax.security.auth.login.*;
38import com.sun.security.auth.callback.*;
39import java.util.HashMap;
40
41public class AuthOnly {
42    private static final String MECH = "GSSAPI";
43    private static final String SERVER_FQDN = "machineX.imc.org";
44    private static final String PROTOCOL = "sample";
45
46    private static String namesfile, proxyfile;
47    private static final byte[] EMPTY = new byte[0];
48    private static boolean auto;
49    private static boolean verbose = false;
50
51    public static void main(String[] args) throws Exception {
52        if (args.length == 0) {
53            namesfile = null;
54            auto = true;
55        } else {
56            int i = 0;
57            if (args[i].equals("-m")) {
58                i++;
59                auto = false;
60            }
61            if (args.length > i) {
62                namesfile = args[i++];
63                if (args.length > i) {
64                    proxyfile = args[i];
65                }
66            } else {
67                namesfile = null;
68            }
69        }
70
71        CallbackHandler clntCbh = null;
72        final CallbackHandler srvCbh = new PropertiesFileCallbackHandler(
73            null, namesfile, proxyfile);
74
75        Subject clntSubj = doLogin("client");
76        Subject srvSubj = doLogin("server");
77        final HashMap clntprops = new HashMap();
78        final HashMap srvprops = new HashMap();
79
80        clntprops.put(Sasl.QOP, "auth");
81        srvprops.put(Sasl.QOP, "auth,auth-int,auth-conf");
82
83        final SaslClient clnt = (SaslClient)
84            Subject.doAs(clntSubj, new PrivilegedExceptionAction() {
85                public Object run() throws Exception {
86                    return Sasl.createSaslClient(
87                        new String[]{MECH}, null, PROTOCOL, SERVER_FQDN,
88                        clntprops, null);
89                }
90            });
91
92        if (verbose) {
93            System.out.println(clntSubj);
94            System.out.println(srvSubj);
95        }
96        final SaslServer srv = (SaslServer)
97            Subject.doAs(srvSubj, new PrivilegedExceptionAction() {
98                public Object run() throws Exception {
99                    return Sasl.createSaslServer(MECH, PROTOCOL, SERVER_FQDN,
100                        srvprops, srvCbh);
101                }
102            });
103
104
105        if (clnt == null) {
106            throw new IllegalStateException(
107                "Unable to find client impl for " + MECH);
108        }
109        if (srv == null) {
110            throw new IllegalStateException(
111                "Unable to find server impl for " + MECH);
112        }
113
114        byte[] response;
115        byte[] challenge;
116
117        response = (byte[]) Subject.doAs(clntSubj,
118            new PrivilegedExceptionAction() {
119            public Object run() throws Exception {
120                return (clnt.hasInitialResponse()? clnt.evaluateChallenge(EMPTY) : EMPTY);
121            }});
122
123        while (!clnt.isComplete() || !srv.isComplete()) {
124            final byte[] responseCopy = response;
125            challenge = (byte[]) Subject.doAs(srvSubj,
126                new PrivilegedExceptionAction() {
127                public Object run() throws Exception {
128                    return srv.evaluateResponse(responseCopy);
129                }});
130
131            if (challenge != null) {
132                final byte[] challengeCopy = challenge;
133                response = (byte[]) Subject.doAs(clntSubj,
134                    new PrivilegedExceptionAction() {
135                    public Object run() throws Exception {
136                        return clnt.evaluateChallenge(challengeCopy);
137                    }});
138            }
139        }
140
141        if (clnt.isComplete() && srv.isComplete()) {
142            if (verbose) {
143                System.out.println("SUCCESS");
144                System.out.println("authzid is " + srv.getAuthorizationID());
145            }
146        } else {
147            throw new IllegalStateException("FAILURE: mismatched state:" +
148                " client complete? " + clnt.isComplete() +
149                " server complete? " + srv.isComplete());
150        }
151    }
152
153    private static Subject doLogin(String msg) throws LoginException {
154        LoginContext lc = null;
155        if (verbose) {
156            System.out.println(msg);
157        }
158        try {
159            lc = new LoginContext(msg, new TextCallbackHandler());
160
161            // Attempt authentication
162            // You might want to do this in a "for" loop to give
163            // user more than one chance to enter correct username/password
164            lc.login();
165
166        } catch (LoginException le) {
167            throw le;
168        }
169        return lc.getSubject();
170    }
171}
172