blob: fd2c925c046930052f3495a42281f0c70cb9f614 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
32package sun.security.krb5.internal;
33
34import sun.security.krb5.*;
35import sun.security.krb5.internal.ccache.CredentialsCache;
36import java.util.StringTokenizer;
37import sun.security.krb5.internal.ktab.*;
38import java.io.File;
39import java.io.IOException;
40import java.util.Date;
41import java.util.Vector;
42import java.io.BufferedReader;
43import java.io.InputStreamReader;
44import java.io.UnsupportedEncodingException;
45import 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 */
52public 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
58en 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
62edential to request service credential
63 * from the foreigh KDC.
64 *
65 * @param service the name of service principal using format components@real
66m
67 * @param ccreds client's initial credential.
68 * @exception Exception general exception will be thrown when any error occu
69rs.
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}