|
1 /* |
|
2 * Portions Copyright 2001-2004 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. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 /* |
|
27 * |
|
28 * (C) Copyright IBM Corp. 1999 All Rights Reserved. |
|
29 * Copyright 1997 The Open Group Research Institute. All rights reserved. |
|
30 */ |
|
31 |
|
32 package sun.security.krb5.internal; |
|
33 |
|
34 import sun.security.krb5.*; |
|
35 import sun.security.krb5.internal.ccache.CredentialsCache; |
|
36 import java.util.StringTokenizer; |
|
37 import sun.security.krb5.internal.ktab.*; |
|
38 import java.io.File; |
|
39 import java.io.IOException; |
|
40 import java.util.Date; |
|
41 import java.util.Vector; |
|
42 import java.io.BufferedReader; |
|
43 import java.io.InputStreamReader; |
|
44 import java.io.UnsupportedEncodingException; |
|
45 import java.net.InetAddress; |
|
46 |
|
47 /** |
|
48 * This class is a utility that contains much of the TGS-Exchange |
|
49 * protocol. It is used by ../Credentials.java for service ticket |
|
50 * acquisition in both the normal and the x-realm case. |
|
51 */ |
|
52 public class CredentialsUtil { |
|
53 |
|
54 private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG; |
|
55 |
|
56 /** |
|
57 * Acquires credentials for a specified service using initial credential. Wh |
|
58 en the service has a different realm |
|
59 * from the initial credential, we do cross-realm authentication - first, we |
|
60 use the current credential to get |
|
61 * a cross-realm credential from the local KDC, then use that cross-realm cr |
|
62 edential to request service credential |
|
63 * from the foreigh KDC. |
|
64 * |
|
65 * @param service the name of service principal using format components@real |
|
66 m |
|
67 * @param ccreds client's initial credential. |
|
68 * @exception Exception general exception will be thrown when any error occu |
|
69 rs. |
|
70 * @return a <code>Credentials</code> object. |
|
71 */ |
|
72 public static Credentials acquireServiceCreds( |
|
73 String service, Credentials ccreds) |
|
74 throws KrbException, IOException { |
|
75 ServiceName sname = new ServiceName(service); |
|
76 String serviceRealm = sname.getRealmString(); |
|
77 String localRealm = ccreds.getClient().getRealmString(); |
|
78 String defaultRealm = Config.getInstance().getDefaultRealm(); |
|
79 |
|
80 if (localRealm == null) { |
|
81 PrincipalName temp = null; |
|
82 if ((temp = ccreds.getServer()) != null) |
|
83 localRealm = temp.getRealmString(); |
|
84 } |
|
85 if (localRealm == null) { |
|
86 localRealm = defaultRealm; |
|
87 } |
|
88 if (serviceRealm == null) { |
|
89 serviceRealm = localRealm; |
|
90 sname.setRealm(serviceRealm); |
|
91 } |
|
92 |
|
93 /* |
|
94 if (!localRealm.equalsIgnoreCase(serviceRealm)) { //do cross-realm auth entication |
|
95 if (DEBUG) { |
|
96 System.out.println(">>>DEBUG: Credentails request cross realm ticket for " + "krbtgt/" + serviceRealm + "@" + localRealm); |
|
97 } |
|
98 Credentials crossCreds = serviceCreds(new ServiceName("krbtgt/" + serviceRealm + "@" + localRealm), ccreds); |
|
99 if (DEBUG) { |
|
100 printDebug(crossCreds); |
|
101 } |
|
102 Credentials result = serviceCreds(sname, crossCreds); |
|
103 if (DEBUG) { |
|
104 printDebug(result); |
|
105 } |
|
106 return result; |
|
107 } |
|
108 else return serviceCreds(sname, ccreds); |
|
109 */ |
|
110 |
|
111 if (localRealm.equals(serviceRealm)) |
|
112 { |
|
113 if (DEBUG) |
|
114 System.out.println(">>> Credentials acquireServiceCreds: same realm"); |
|
115 return serviceCreds(sname, ccreds); |
|
116 } |
|
117 |
|
118 // Get a list of realms to traverse |
|
119 String[] realms = Realm.getRealmsList(localRealm, serviceRealm); |
|
120 |
|
121 if (realms == null || realms.length == 0) |
|
122 { |
|
123 if (DEBUG) |
|
124 System.out.println(">>> Credentials acquireServiceCreds: no realms list"); |
|
125 return null; |
|
126 } |
|
127 |
|
128 int i = 0, k = 0; |
|
129 Credentials cTgt = null, newTgt = null, theTgt = null; |
|
130 ServiceName tempService = null; |
|
131 String realm = null, newTgtRealm = null, theTgtRealm = null; |
|
132 |
|
133 for (cTgt = ccreds, i = 0; i < realms.length;) |
|
134 { |
|
135 tempService = new ServiceName(PrincipalName.TGS_DEFAULT_SRV_NAME, |
|
136 serviceRealm, realms[i]); |
|
137 |
|
138 if (DEBUG) |
|
139 { |
|
140 System.out.println(">>> Credentials acquireServiceCreds: main loop: [" + i +"] tempService=" + tempService); |
|
141 } |
|
142 |
|
143 try { |
|
144 newTgt = serviceCreds(tempService, cTgt); |
|
145 } catch (Exception exc) { |
|
146 newTgt = null; |
|
147 } |
|
148 |
|
149 if (newTgt == null) |
|
150 { |
|
151 if (DEBUG) |
|
152 { |
|
153 System.out.println(">>> Credentials acquireServiceCreds: no tgt; searching backwards"); |
|
154 } |
|
155 |
|
156 /* |
|
157 * No tgt found. Try to get one for a |
|
158 * realm as close to the target as possible. |
|
159 * That means traversing the realms list backwards. |
|
160 */ |
|
161 |
|
162 for (newTgt = null, k = realms.length - 1; |
|
163 newTgt == null && k > i; k--) |
|
164 { |
|
165 |
|
166 tempService = new ServiceName( |
|
167 PrincipalName.TGS_DEFAULT_SRV_NAME, |
|
168 realms[k], realms[i]); |
|
169 if (DEBUG) |
|
170 { |
|
171 System.out.println(">>> Credentials acquireServiceCreds: inner loop: [" + k +"] tempService=" + tempService); |
|
172 } |
|
173 |
|
174 try { |
|
175 newTgt = serviceCreds(tempService, cTgt); |
|
176 } catch (Exception exc) { |
|
177 newTgt = null; |
|
178 } |
|
179 } |
|
180 } // Ends 'if (newTgt == null)' |
|
181 |
|
182 if (newTgt == null) |
|
183 { |
|
184 if (DEBUG) |
|
185 { |
|
186 System.out.println(">>> Credentials acquireServiceCreds: no tgt; cannot get creds"); |
|
187 } |
|
188 break; |
|
189 } |
|
190 |
|
191 /* |
|
192 * We have a tgt. It may or may not be for the target. |
|
193 * If it's for the target realm, we're done looking for a tgt. |
|
194 */ |
|
195 |
|
196 newTgtRealm = newTgt.getServer().getInstanceComponent(); |
|
197 |
|
198 if (DEBUG) |
|
199 { |
|
200 System.out.println(">>> Credentials acquireServiceCreds: got tgt"); |
|
201 //printDebug(newTgt); |
|
202 } |
|
203 |
|
204 if (newTgtRealm.equals(serviceRealm)) |
|
205 { |
|
206 /* We got the right tgt */ |
|
207 theTgt = newTgt; |
|
208 theTgtRealm = newTgtRealm; |
|
209 break; |
|
210 } |
|
211 |
|
212 /* |
|
213 * The new tgt is not for the target realm. |
|
214 * See if the realm of the new tgt is in the list of realms |
|
215 * and continue looking from there. |
|
216 */ |
|
217 |
|
218 for (k = i+1; k < realms.length; k++) |
|
219 { |
|
220 if (newTgtRealm.equals(realms[k])) |
|
221 { |
|
222 break; |
|
223 } |
|
224 } |
|
225 |
|
226 if (k < realms.length) |
|
227 { |
|
228 /* |
|
229 * (re)set the counter so we start looking |
|
230 * from the realm we just obtained a tgt for. |
|
231 */ |
|
232 i = k; |
|
233 cTgt = newTgt; |
|
234 |
|
235 if (DEBUG) |
|
236 { |
|
237 System.out.println(">>> Credentials acquireServiceCreds: continuing with main loop counter reset to " + i); |
|
238 } |
|
239 |
|
240 continue; |
|
241 } |
|
242 else |
|
243 { |
|
244 /* |
|
245 * The new tgt's realm is not in the heirarchy of realms. |
|
246 * It's probably not safe to get a tgt from |
|
247 * a tgs that is outside the known list of realms. |
|
248 * Give up now. |
|
249 */ |
|
250 |
|
251 break; |
|
252 } |
|
253 } // Ends outermost/main 'for' loop |
|
254 |
|
255 Credentials theCreds = null; |
|
256 |
|
257 if (theTgt != null) |
|
258 { |
|
259 /* We have the right tgt. Let's get the service creds */ |
|
260 |
|
261 if (DEBUG) |
|
262 { |
|
263 System.out.println(">>> Credentials acquireServiceCreds: got right tgt"); |
|
264 |
|
265 //printDebug(theTgt); |
|
266 |
|
267 System.out.println(">>> Credentials acquireServiceCreds: obtaining service creds for " + sname); |
|
268 } |
|
269 |
|
270 try { |
|
271 theCreds = serviceCreds(sname, theTgt); |
|
272 } catch (Exception exc) { |
|
273 if (DEBUG) |
|
274 System.out.println(exc); |
|
275 theCreds = null; |
|
276 } |
|
277 } |
|
278 |
|
279 if (theCreds != null) |
|
280 { |
|
281 if (DEBUG) |
|
282 { |
|
283 System.out.println(">>> Credentials acquireServiceCreds: returning creds:"); |
|
284 Credentials.printDebug(theCreds); |
|
285 } |
|
286 return theCreds; |
|
287 } |
|
288 throw new KrbApErrException(Krb5.KRB_AP_ERR_GEN_CRED, |
|
289 "No service creds"); |
|
290 } |
|
291 |
|
292 /* |
|
293 * This method does the real job to request the service credential. |
|
294 */ |
|
295 private static Credentials serviceCreds( |
|
296 ServiceName service, Credentials ccreds) |
|
297 throws KrbException, IOException { |
|
298 return new KrbTgsReq(ccreds, service).sendAndGetCreds(); |
|
299 } |
|
300 } |