1 /*
2  * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 import java.security.Principal;
25 import java.util.Arrays;
26 import java.util.Locale;
27 import javax.security.auth.Subject;
28 import javax.security.auth.callback.Callback;
29 import javax.security.auth.callback.CallbackHandler;
30 import javax.security.auth.callback.ChoiceCallback;
31 import javax.security.auth.callback.ConfirmationCallback;
32 import javax.security.auth.callback.LanguageCallback;
33 import javax.security.auth.callback.NameCallback;
34 import javax.security.auth.callback.PasswordCallback;
35 import javax.security.auth.callback.TextInputCallback;
36 import javax.security.auth.callback.TextOutputCallback;
37 import javax.security.auth.callback.UnsupportedCallbackException;
38 import javax.security.auth.login.LoginContext;
39 import javax.security.auth.login.LoginException;
40 
41 /*
42  * @test
43  * @bug 8048138
44  * @summary Checks if JAAS login works fine with standard callbacks
45  * @compile DefaultHandlerModule.java
46  * @run main/othervm StandardCallbacks
47  */
48 public class StandardCallbacks {
49 
50     private static final String USERNAME = "username";
51     private static final char[] PASSWORD = "password".toCharArray();
52 
main(String[] args)53     public static void main(String[] args) throws LoginException {
54         System.setProperty("java.security.auth.login.config",
55                 System.getProperty("test.src")
56                         + System.getProperty("file.separator")
57                         + "custom.config");
58 
59         CustomCallbackHandler handler = new CustomCallbackHandler(USERNAME);
60         LoginContext context = new LoginContext("StandardCallbacks", handler);
61 
62         handler.setPassword(PASSWORD);
63         System.out.println("Try to login with correct password, "
64                 + "successful authentication is expected");
65         context.login();
66         System.out.println("Authentication succeeded!");
67 
68         Subject subject = context.getSubject();
69         System.out.println("Authenticated user has the following principals ["
70                 + subject.getPrincipals().size() + " ]:");
71         boolean found = true;
72         for (Principal principal : subject.getPrincipals()) {
73             System.out.println("principal: " + principal);
74             if (principal instanceof CustomLoginModule.TestPrincipal) {
75                 CustomLoginModule.TestPrincipal testPrincipal =
76                         (CustomLoginModule.TestPrincipal) principal;
77                 if (USERNAME.equals(testPrincipal.getName())) {
78                     System.out.println("Found test principal: "
79                             + testPrincipal);
80                     found = true;
81                     break;
82                 }
83             }
84         }
85 
86         if (!found) {
87             throw new RuntimeException("TestPrincipal not found");
88         }
89 
90         // check if all expected text output callbacks have been called
91         if (!handler.info) {
92             throw new RuntimeException("TextOutputCallback.INFO not called");
93         }
94 
95         if (!handler.warning) {
96             throw new RuntimeException("TextOutputCallback.WARNING not called");
97         }
98 
99         if (!handler.error) {
100             throw new RuntimeException("TextOutputCallback.ERROR not called");
101         }
102 
103         System.out.println("Authenticated user has the following public "
104                 + "credentials [" + subject.getPublicCredentials().size()
105                 + "]:");
106         subject.getPublicCredentials().stream().
107                 forEach((o) -> {
108                     System.out.println("public credential: " + o);
109         });
110 
111         context.logout();
112 
113         System.out.println("Test passed");
114     }
115 
116     private static class CustomCallbackHandler implements CallbackHandler {
117 
118         private final String username;
119         private char[] password;
120         private boolean info = false;
121         private boolean warning = false;
122         private boolean error = false;
123 
CustomCallbackHandler(String username)124         CustomCallbackHandler(String username) {
125             this.username = username;
126         }
127 
setPassword(char[] password)128         void setPassword(char[] password) {
129             this.password = password;
130         }
131 
132         @Override
handle(Callback[] callbacks)133         public void handle(Callback[] callbacks)
134                 throws UnsupportedCallbackException {
135             for (Callback callback : callbacks) {
136                 if (callback instanceof TextOutputCallback) {
137                     TextOutputCallback toc = (TextOutputCallback) callback;
138                     switch (toc.getMessageType()) {
139                         case TextOutputCallback.INFORMATION:
140                             System.out.println("INFO: " + toc.getMessage());
141                             info = true;
142                             break;
143                         case TextOutputCallback.ERROR:
144                             System.out.println("ERROR: " + toc.getMessage());
145                             error = true;
146                             break;
147                         case TextOutputCallback.WARNING:
148                             System.out.println("WARNING: " + toc.getMessage());
149                             warning = true;
150                             break;
151                         default:
152                             throw new UnsupportedCallbackException(toc,
153                                     "Unsupported message type: "
154                                             + toc.getMessageType());
155                     }
156                 } else if (callback instanceof TextInputCallback) {
157                     TextInputCallback tic = (TextInputCallback) callback;
158                     System.out.println(tic.getPrompt());
159                     tic.setText(CustomLoginModule.HELLO);
160                 } else if (callback instanceof LanguageCallback) {
161                     LanguageCallback lc = (LanguageCallback) callback;
162                     lc.setLocale(Locale.GERMANY);
163                 } else if (callback instanceof ConfirmationCallback) {
164                     ConfirmationCallback cc = (ConfirmationCallback) callback;
165                     System.out.println(cc.getPrompt());
166                     cc.setSelectedIndex(ConfirmationCallback.YES);
167                 } else if (callback instanceof ChoiceCallback) {
168                     ChoiceCallback cc = (ChoiceCallback) callback;
169                     System.out.println(cc.getPrompt()
170                             + Arrays.toString(cc.getChoices()));
171                     cc.setSelectedIndex(0);
172                 } else if (callback instanceof NameCallback) {
173                     NameCallback nc = (NameCallback) callback;
174                     System.out.println(nc.getPrompt());
175                     nc.setName(username);
176                 } else if (callback instanceof PasswordCallback) {
177                     PasswordCallback pc = (PasswordCallback) callback;
178                     System.out.println(pc.getPrompt());
179                     pc.setPassword(password);
180                 } else {
181                     throw new UnsupportedCallbackException(callback,
182                             "Unknown callback");
183                 }
184             }
185         }
186 
187     }
188 
189 }
190