Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/sun/security/jgss/GSSUtil.java
+++ new/src/share/classes/sun/security/jgss/GSSUtil.java
1 1 /*
2 2 * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Sun designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Sun in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 23 * have any questions.
24 24 */
25 25
26 26 package sun.security.jgss;
27 27
28 28 import com.sun.security.auth.callback.TextCallbackHandler;
29 29 import javax.security.auth.Subject;
30 30 import javax.security.auth.kerberos.KerberosPrincipal;
31 31 import javax.security.auth.kerberos.KerberosTicket;
32 32 import javax.security.auth.kerberos.KerberosKey;
33 33 import org.ietf.jgss.*;
34 34 import sun.security.jgss.spi.GSSNameSpi;
35 35 import sun.security.jgss.spi.GSSCredentialSpi;
36 36 import sun.security.action.GetPropertyAction;
37 37 import sun.security.jgss.krb5.Krb5NameElement;
38 38 import sun.security.jgss.spnego.SpNegoCredElement;
39 39 import java.util.Set;
40 40 import java.util.HashSet;
41 41 import java.util.Vector;
42 42 import java.util.Iterator;
43 43 import java.security.AccessController;
44 44 import java.security.AccessControlContext;
45 45 import java.security.PrivilegedExceptionAction;
46 46 import java.security.PrivilegedActionException;
47 47 import javax.security.auth.callback.CallbackHandler;
48 48 import javax.security.auth.login.LoginContext;
49 49 import javax.security.auth.login.LoginException;
50 50 import sun.security.action.GetBooleanAction;
51 51
52 52 /**
53 53 * The GSSUtilImplementation that knows how to work with the internals of
54 54 * the GSS-API.
55 55 */
56 56 public class GSSUtil {
57 57
58 58 public static final Oid GSS_KRB5_MECH_OID =
59 59 GSSUtil.createOid("1.2.840.113554.1.2.2");
60 60 public static final Oid GSS_KRB5_MECH_OID2 =
61 61 GSSUtil.createOid("1.3.5.1.5.2");
62 62
63 63 public static final Oid GSS_SPNEGO_MECH_OID =
64 64 GSSUtil.createOid("1.3.6.1.5.5.2");
65 65
66 66 public static final Oid NT_GSS_KRB5_PRINCIPAL =
67 67 GSSUtil.createOid("1.2.840.113554.1.2.2.1");
68 68
69 69 public static final Oid NT_HOSTBASED_SERVICE2 =
70 70 GSSUtil.createOid("1.2.840.113554.1.2.1.4");
71 71
72 72 private static final String DEFAULT_HANDLER =
73 73 "auth.login.defaultCallbackHandler";
74 74
75 75 static final boolean DEBUG;
76 76 static {
77 77 DEBUG = (AccessController.doPrivileged
78 78 (new GetBooleanAction("sun.security.jgss.debug"))).
79 79 booleanValue();
80 80 }
81 81
82 82 static void debug(String message) {
83 83 if (DEBUG) {
84 84 assert(message != null);
85 85 System.out.println(message);
86 86 }
87 87 }
88 88
89 89 // NOTE: this method is only for creating Oid objects with
90 90 // known to be valid <code>oidStr</code> given it ignores
91 91 // the GSSException
92 92 public static Oid createOid(String oidStr) {
93 93 try {
94 94 return new Oid(oidStr);
95 95 } catch (GSSException e) {
96 96 debug("Ignored invalid OID: " + oidStr);
97 97 return null;
98 98 }
99 99 }
100 100
101 101 public static boolean isSpNegoMech(Oid oid) {
102 102 return (GSS_SPNEGO_MECH_OID.equals(oid));
103 103 }
104 104
105 105 public static boolean isKerberosMech(Oid oid) {
106 106 return (GSS_KRB5_MECH_OID.equals(oid) ||
107 107 GSS_KRB5_MECH_OID2.equals(oid));
108 108
109 109 }
110 110
111 111 public static String getMechStr(Oid oid) {
112 112 if (isSpNegoMech(oid)) {
113 113 return "SPNEGO";
114 114 } else if (isKerberosMech(oid)) {
115 115 return "Kerberos V5";
116 116 } else {
117 117 return oid.toString();
118 118 }
119 119 }
120 120
121 121 /**
122 122 * Note: The current impl only works with Sun's impl of
123 123 * GSSName and GSSCredential since it depends on package
124 124 * private APIs.
125 125 */
126 126 public static Subject getSubject(GSSName name,
127 127 GSSCredential creds) {
128 128
129 129 HashSet<Object> privCredentials = null;
130 130 HashSet<Object> pubCredentials = new HashSet<Object>(); // empty Set
131 131
132 132 Set<GSSCredentialSpi> gssCredentials = null;
133 133
134 134 Set<KerberosPrincipal> krb5Principals =
135 135 new HashSet<KerberosPrincipal>();
136 136
137 137 if (name instanceof GSSNameImpl) {
138 138 try {
139 139 GSSNameSpi ne = ((GSSNameImpl) name).getElement
140 140 (GSS_KRB5_MECH_OID);
141 141 String krbName = ne.toString();
142 142 if (ne instanceof Krb5NameElement) {
143 143 krbName =
144 144 ((Krb5NameElement) ne).getKrb5PrincipalName().getName();
145 145 }
146 146 KerberosPrincipal krbPrinc = new KerberosPrincipal(krbName);
147 147 krb5Principals.add(krbPrinc);
148 148 } catch (GSSException ge) {
149 149 debug("Skipped name " + name + " due to " + ge);
150 150 }
151 151 }
152 152
153 153 if (creds instanceof GSSCredentialImpl) {
154 154 gssCredentials = ((GSSCredentialImpl) creds).getElements();
155 155 privCredentials = new HashSet<Object>(gssCredentials.size());
156 156 populateCredentials(privCredentials, gssCredentials);
157 157 } else {
158 158 privCredentials = new HashSet<Object>(); // empty Set
159 159 }
160 160 debug("Created Subject with the following");
161 161 debug("principals=" + krb5Principals);
162 162 debug("public creds=" + pubCredentials);
163 163 debug("private creds=" + privCredentials);
164 164
165 165 return new Subject(false, krb5Principals, pubCredentials,
166 166 privCredentials);
167 167
168 168 }
169 169
170 170 /**
171 171 * Populates the set credentials with elements from gssCredentials. At
172 172 * the same time, it converts any subclasses of KerberosTicket
173 173 * into KerberosTicket instances and any subclasses of KerberosKey into
174 174 * KerberosKey instances. (It is not desirable to expose the customer
175 175 * to sun.security.jgss.krb5.Krb5InitCredential which extends
176 176 * KerberosTicket and sun.security.jgss.krb5.Kbr5AcceptCredential which
177 177 * extends KerberosKey.)
178 178 */
179 179 private static void populateCredentials(Set<Object> credentials,
180 180 Set<?> gssCredentials) {
181 181
182 182 Object cred;
183 183
184 184 Iterator<?> elements = gssCredentials.iterator();
185 185 while (elements.hasNext()) {
186 186
187 187 cred = elements.next();
188 188
189 189 // Retrieve the internal cred out of SpNegoCredElement
190 190 if (cred instanceof SpNegoCredElement) {
191 191 cred = ((SpNegoCredElement) cred).getInternalCred();
192 192 }
193 193
194 194 if (cred instanceof KerberosTicket) {
195 195 if (!cred.getClass().getName().equals
196 196 ("javax.security.auth.kerberos.KerberosTicket")) {
197 197 KerberosTicket tempTkt = (KerberosTicket) cred;
198 198 cred = new KerberosTicket(tempTkt.getEncoded(),
199 199 tempTkt.getClient(),
200 200 tempTkt.getServer(),
201 201 tempTkt.getSessionKey().getEncoded(),
202 202 tempTkt.getSessionKeyType(),
203 203 tempTkt.getFlags(),
204 204 tempTkt.getAuthTime(),
205 205 tempTkt.getStartTime(),
206 206 tempTkt.getEndTime(),
207 207 tempTkt.getRenewTill(),
208 208 tempTkt.getClientAddresses());
209 209 }
210 210 credentials.add(cred);
211 211 } else if (cred instanceof KerberosKey) {
212 212 if (!cred.getClass().getName().equals
213 213 ("javax.security.auth.kerberos.KerberosKey")) {
214 214 KerberosKey tempKey = (KerberosKey) cred;
215 215 cred = new KerberosKey(tempKey.getPrincipal(),
216 216 tempKey.getEncoded(),
217 217 tempKey.getKeyType(),
218 218 tempKey.getVersionNumber());
219 219 }
220 220 credentials.add(cred);
221 221 } else {
222 222 // Ignore non-KerberosTicket and non-KerberosKey elements
223 223 debug("Skipped cred element: " + cred);
224 224 }
225 225 }
226 226 }
227 227
228 228 /**
229 229 * Authenticate using the login module from the specified
↓ open down ↓ |
229 lines elided |
↑ open up ↑ |
230 230 * configuration entry.
231 231 *
232 232 * @param caller the caller of JAAS Login
233 233 * @param mech the mech to be used
234 234 * @return the authenticated subject
235 235 */
236 236 public static Subject login(GSSCaller caller, Oid mech) throws LoginException {
237 237
238 238 CallbackHandler cb = null;
239 239 if (caller instanceof HttpCaller) {
240 - cb = new sun.net.www.protocol.http.NegotiateCallbackHandler(
240 + cb = new sun.net.www.protocol.http.spnego.NegotiateCallbackHandler(
241 241 ((HttpCaller)caller).info());
242 242 } else {
243 243 String defaultHandler =
244 244 java.security.Security.getProperty(DEFAULT_HANDLER);
245 245 // get the default callback handler
246 246 if ((defaultHandler != null) && (defaultHandler.length() != 0)) {
247 247 cb = null;
248 248 } else {
249 249 cb = new TextCallbackHandler();
250 250 }
251 251 }
252 252
253 253 // New instance of LoginConfigImpl must be created for each login,
254 254 // since the entry name is not passed as the first argument, but
255 255 // generated with caller and mech inside LoginConfigImpl
256 256 LoginContext lc = new LoginContext("", null, cb,
257 257 new LoginConfigImpl(caller, mech));
258 258 lc.login();
259 259 return lc.getSubject();
260 260 }
261 261
262 262 /**
263 263 * Determines if the application doesn't mind if the mechanism obtains
264 264 * the required credentials from outside of the current Subject. Our
265 265 * Kerberos v5 mechanism would do a JAAS login on behalf of the
266 266 * application if this were the case.
267 267 *
268 268 * The application indicates this by explicitly setting the system
269 269 * property javax.security.auth.useSubjectCredsOnly to false.
270 270 */
271 271 public static boolean useSubjectCredsOnly(GSSCaller caller) {
272 272
273 273 // HTTP/SPNEGO doesn't use the standard JAAS framework. Instead, it
274 274 // uses the java.net.Authenticator style, therefore always return
275 275 // false here.
276 276 if (caller instanceof HttpCaller) {
277 277 return false;
278 278 }
279 279 /*
280 280 * Don't use GetBooleanAction because the default value in the JRE
281 281 * (when this is unset) has to treated as true.
282 282 */
283 283 String propValue = AccessController.doPrivileged(
284 284 new GetPropertyAction("javax.security.auth.useSubjectCredsOnly",
285 285 "true"));
286 286 /*
287 287 * This property has to be explicitly set to "false". Invalid
288 288 * values should be ignored and the default "true" assumed.
289 289 */
290 290 return (!propValue.equalsIgnoreCase("false"));
291 291 }
292 292
293 293 /**
294 294 * Determines the SPNEGO interoperability mode with Microsoft;
295 295 * by default it is set to true.
296 296 *
297 297 * To disable it, the application indicates this by explicitly setting
298 298 * the system property sun.security.spnego.interop to false.
299 299 */
300 300 public static boolean useMSInterop() {
301 301 /*
302 302 * Don't use GetBooleanAction because the default value in the JRE
303 303 * (when this is unset) has to treated as true.
304 304 */
305 305 String propValue = AccessController.doPrivileged(
306 306 new GetPropertyAction("sun.security.spnego.msinterop",
307 307 "true"));
308 308 /*
309 309 * This property has to be explicitly set to "false". Invalid
310 310 * values should be ignored and the default "true" assumed.
311 311 */
312 312 return (!propValue.equalsIgnoreCase("false"));
313 313 }
314 314
315 315 /**
316 316 * Searches the private credentials of current Subject with the
317 317 * specified criteria and returns the matching GSSCredentialSpi
318 318 * object out of Sun's impl of GSSCredential. Returns null if
319 319 * no Subject present or a Vector which contains 0 or more
320 320 * matching GSSCredentialSpi objects.
321 321 */
322 322 public static Vector searchSubject(final GSSNameSpi name,
323 323 final Oid mech,
324 324 final boolean initiate,
325 325 final Class credCls) {
326 326 debug("Search Subject for " + getMechStr(mech) +
327 327 (initiate? " INIT" : " ACCEPT") + " cred (" +
328 328 (name == null? "<<DEF>>" : name.toString()) + ", " +
329 329 credCls.getName() + ")");
330 330 final AccessControlContext acc = AccessController.getContext();
331 331 try {
332 332 Vector creds =
333 333 AccessController.doPrivileged
334 334 (new PrivilegedExceptionAction<Vector>() {
335 335 public Vector run() throws Exception {
336 336 Subject accSubj = Subject.getSubject(acc);
337 337 Vector<GSSCredentialSpi> result = null;
338 338 if (accSubj != null) {
339 339 result = new Vector<GSSCredentialSpi>();
340 340 Iterator<GSSCredentialImpl> iterator =
341 341 accSubj.getPrivateCredentials
342 342 (GSSCredentialImpl.class).iterator();
343 343 while (iterator.hasNext()) {
344 344 GSSCredentialImpl cred = iterator.next();
345 345 debug("...Found cred" + cred);
346 346 try {
347 347 GSSCredentialSpi ce =
348 348 cred.getElement(mech, initiate);
349 349 debug("......Found element: " + ce);
350 350 if (ce.getClass().equals(credCls) &&
351 351 (name == null ||
352 352 name.equals((Object) ce.getName()))) {
353 353 result.add(ce);
354 354 } else {
355 355 debug("......Discard element");
356 356 }
357 357 } catch (GSSException ge) {
358 358 debug("...Discard cred (" + ge + ")");
359 359 }
360 360 }
361 361 } else debug("No Subject");
362 362 return result;
363 363 }
364 364 });
365 365 return creds;
366 366 } catch (PrivilegedActionException pae) {
367 367 debug("Unexpected exception when searching Subject:");
368 368 if (DEBUG) pae.printStackTrace();
369 369 return null;
370 370 }
371 371 }
372 372 }
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX