get_creds.c (505d05c7) get_creds.c (159d09a2)
1/*
1/*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
3 * Use is subject to license terms.
4 */
5
6#pragma ident "%Z%%M% %I% %E% SMI"
7
8/*
9 * lib/krb5/krb/get_creds.c
10 *
11 * Copyright 1990 by the Massachusetts Institute of Technology.
12 * All Rights Reserved.
13 *
14 * Export of this software from the United States of America may
15 * require a specific license from the United States Government.
16 * It is the responsibility of any person or organization contemplating
17 * export to obtain such a license before exporting.
6
7/*
8 * lib/krb5/krb/get_creds.c
9 *
10 * Copyright 1990 by the Massachusetts Institute of Technology.
11 * All Rights Reserved.
12 *
13 * Export of this software from the United States of America may
14 * require a specific license from the United States Government.
15 * It is the responsibility of any person or organization contemplating
16 * export to obtain such a license before exporting.
18 *
17 *
19 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20 * distribute this software and its documentation for any purpose and
21 * without fee is hereby granted, provided that the above copyright
22 * notice appear in all copies and that both that copyright notice and
23 * this permission notice appear in supporting documentation, and that
24 * the name of M.I.T. not be used in advertising or publicity pertaining
25 * to distribution of the software without specific, written prior
26 * permission. Furthermore if you modify this software you must label
27 * your software as modified software and not distribute it in such a
28 * fashion that it might be confused with the original M.I.T. software.
29 * M.I.T. makes no representations about the suitability of
30 * this software for any purpose. It is provided "as is" without express
31 * or implied warranty.
18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19 * distribute this software and its documentation for any purpose and
20 * without fee is hereby granted, provided that the above copyright
21 * notice appear in all copies and that both that copyright notice and
22 * this permission notice appear in supporting documentation, and that
23 * the name of M.I.T. not be used in advertising or publicity pertaining
24 * to distribution of the software without specific, written prior
25 * permission. Furthermore if you modify this software you must label
26 * your software as modified software and not distribute it in such a
27 * fashion that it might be confused with the original M.I.T. software.
28 * M.I.T. makes no representations about the suitability of
29 * this software for any purpose. It is provided "as is" without express
30 * or implied warranty.
31 *
32 *
32 *
33 *
34 * krb5_get_credentials()
35 */
36
37
38
39/*
40 Attempts to use the credentials cache or TGS exchange to get an additional
41 ticket for the
42 client identified by in_creds->client, the server identified by
43 in_creds->server, with options options, expiration date specified in
44 in_creds->times.endtime (0 means as long as possible), session key type
45 specified in in_creds->keyblock.enctype (if non-zero)
46
47 Any returned ticket and intermediate ticket-granting tickets are
48 stored in ccache.
49
50 returns errors from encryption routines, system errors
51 */
52
33 * krb5_get_credentials()
34 */
35
36
37
38/*
39 Attempts to use the credentials cache or TGS exchange to get an additional
40 ticket for the
41 client identified by in_creds->client, the server identified by
42 in_creds->server, with options options, expiration date specified in
43 in_creds->times.endtime (0 means as long as possible), session key type
44 specified in in_creds->keyblock.enctype (if non-zero)
45
46 Any returned ticket and intermediate ticket-granting tickets are
47 stored in ccache.
48
49 returns errors from encryption routines, system errors
50 */
51
53#include <k5-int.h>
52#include "k5-int.h"
54
55/*ARGSUSED*/
56static krb5_error_code
57krb5_get_credentials_core(krb5_context context, krb5_flags options,
58 krb5_creds *in_creds, krb5_creds *mcreds,
59 krb5_flags *fields)
60{
53
54/*ARGSUSED*/
55static krb5_error_code
56krb5_get_credentials_core(krb5_context context, krb5_flags options,
57 krb5_creds *in_creds, krb5_creds *mcreds,
58 krb5_flags *fields)
59{
60 /* Solaris Kerberos */
61 krb5_error_code ret = 0;
62
63 if (!in_creds || !in_creds->server || !in_creds->client)
64 return EINVAL;
65
66 memset((char *)mcreds, 0, sizeof(krb5_creds));
67 mcreds->magic = KV5M_CREDS;
68 /*
61 krb5_error_code ret = 0;
62
63 if (!in_creds || !in_creds->server || !in_creds->client)
64 return EINVAL;
65
66 memset((char *)mcreds, 0, sizeof(krb5_creds));
67 mcreds->magic = KV5M_CREDS;
68 /*
69 * Solaris Kerberos:
69 * Set endtime appropriately to make sure we do not rope in
70 * expired creds. If endtime is set to 0 (which it almost always
71 * is, courtesy memset/calloc) the krb5_cc_retrieve_cred() call in
72 * krb5_get_credentials() with KRB5_TC_MATCH_TIMES will
73 * succeed and return the expired cred.
74 *
75 * Hence, endtime below is set to "now" if in_creds->times.endtime
76 * is 0, so that krb5_cc_retrieve_cred fails and we get fresh creds,

--- 8 unchanged lines hidden (view full) ---

85 ret = krb5_copy_keyblock_data(context, &in_creds->keyblock,
86 &mcreds->keyblock);
87 if (ret)
88 return (ret);
89
90 mcreds->authdata = in_creds->authdata;
91 mcreds->server = in_creds->server;
92 mcreds->client = in_creds->client;
70 * Set endtime appropriately to make sure we do not rope in
71 * expired creds. If endtime is set to 0 (which it almost always
72 * is, courtesy memset/calloc) the krb5_cc_retrieve_cred() call in
73 * krb5_get_credentials() with KRB5_TC_MATCH_TIMES will
74 * succeed and return the expired cred.
75 *
76 * Hence, endtime below is set to "now" if in_creds->times.endtime
77 * is 0, so that krb5_cc_retrieve_cred fails and we get fresh creds,

--- 8 unchanged lines hidden (view full) ---

86 ret = krb5_copy_keyblock_data(context, &in_creds->keyblock,
87 &mcreds->keyblock);
88 if (ret)
89 return (ret);
90
91 mcreds->authdata = in_creds->authdata;
92 mcreds->server = in_creds->server;
93 mcreds->client = in_creds->client;
93
94
94 *fields = KRB5_TC_MATCH_TIMES /*XXX |KRB5_TC_MATCH_SKEY_TYPE */
95 | KRB5_TC_MATCH_AUTHDATA
96 | KRB5_TC_SUPPORTED_KTYPES;
97 if (mcreds->keyblock.enctype) {
98 krb5_enctype *ktypes;
99 int i;
100
101 *fields |= KRB5_TC_MATCH_KTYPE;
102 ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes);
103 for (i = 0; ktypes[i]; i++)
95 *fields = KRB5_TC_MATCH_TIMES /*XXX |KRB5_TC_MATCH_SKEY_TYPE */
96 | KRB5_TC_MATCH_AUTHDATA
97 | KRB5_TC_SUPPORTED_KTYPES;
98 if (mcreds->keyblock.enctype) {
99 krb5_enctype *ktypes;
100 int i;
101
102 *fields |= KRB5_TC_MATCH_KTYPE;
103 ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes);
104 for (i = 0; ktypes[i]; i++)
104 if (ktypes[i] == mcreds->keyblock.enctype)
105 if (ktypes[i] == mcreds->keyblock.enctype)
105 break;
106 if (ktypes[i] == 0)
106 break;
107 if (ktypes[i] == 0)
107 ret = KRB5_CC_NOT_KTYPE;
108 ret = KRB5_CC_NOT_KTYPE;
108 free (ktypes);
109 if (ret)
109 free (ktypes);
110 if (ret)
110 return ret;
111 return ret;
111 }
112 if (options & KRB5_GC_USER_USER) {
113 /* also match on identical 2nd tkt and tkt encrypted in a
114 session key */
115 *fields |= KRB5_TC_MATCH_2ND_TKT|KRB5_TC_MATCH_IS_SKEY;
116 mcreds->is_skey = TRUE;
117 mcreds->second_ticket = in_creds->second_ticket;
118 if (!in_creds->second_ticket.length)

--- 23 unchanged lines hidden (view full) ---

142
143 if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL)
144 return ENOMEM;
145
146 memset((char *)ncreds, 0, sizeof(krb5_creds));
147 ncreds->magic = KV5M_CREDS;
148
149 /* The caller is now responsible for cleaning up in_creds */
112 }
113 if (options & KRB5_GC_USER_USER) {
114 /* also match on identical 2nd tkt and tkt encrypted in a
115 session key */
116 *fields |= KRB5_TC_MATCH_2ND_TKT|KRB5_TC_MATCH_IS_SKEY;
117 mcreds->is_skey = TRUE;
118 mcreds->second_ticket = in_creds->second_ticket;
119 if (!in_creds->second_ticket.length)

--- 23 unchanged lines hidden (view full) ---

143
144 if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL)
145 return ENOMEM;
146
147 memset((char *)ncreds, 0, sizeof(krb5_creds));
148 ncreds->magic = KV5M_CREDS;
149
150 /* The caller is now responsible for cleaning up in_creds */
151 /* Solaris Kerberos */
150 if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds,
151 ncreds)) !=0) {
152 krb5_xfree(ncreds);
153 ncreds = in_creds;
154 } else {
155 *out_creds = ncreds;
156 }
157

--- 6 unchanged lines hidden (view full) ---

164 else
165 not_ktype = 0;
166
167 retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts);
168 if (tgts) {
169 register int i = 0;
170 krb5_error_code rv2;
171 while (tgts[i]) {
152 if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds,
153 ncreds)) !=0) {
154 krb5_xfree(ncreds);
155 ncreds = in_creds;
156 } else {
157 *out_creds = ncreds;
158 }
159

--- 6 unchanged lines hidden (view full) ---

166 else
167 not_ktype = 0;
168
169 retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts);
170 if (tgts) {
171 register int i = 0;
172 krb5_error_code rv2;
173 while (tgts[i]) {
174 /* Solaris Kerberos */
172 if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i])) != 0) {
173 retval = rv2;
174 break;
175 }
176 i++;
177 }
178 krb5_free_tgt_creds(context, tgts);
179 }

--- 7 unchanged lines hidden (view full) ---

187 * krb5_get_cred_from_kdc() is semantically incorrect, since the
188 * actual failure was the non-existence of a ticket of the correct
189 * enctype rather than the missing TGT.
190 */
191 if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE)
192 && not_ktype)
193 retval = KRB5_CC_NOT_KTYPE;
194
175 if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i])) != 0) {
176 retval = rv2;
177 break;
178 }
179 i++;
180 }
181 krb5_free_tgt_creds(context, tgts);
182 }

--- 7 unchanged lines hidden (view full) ---

190 * krb5_get_cred_from_kdc() is semantically incorrect, since the
191 * actual failure was the non-existence of a ticket of the correct
192 * enctype rather than the missing TGT.
193 */
194 if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE)
195 && not_ktype)
196 retval = KRB5_CC_NOT_KTYPE;
197
195 if (!retval)
198 if (!retval) {
199 /* the purpose of the krb5_get_credentials call is to
200 * obtain a set of credentials for the caller. the
201 * krb5_cc_store_cred() call is to optimize performance
202 * for future calls. Ignore any errors, since the credentials
203 * are still valid even if we fail to store them in the cache.
204 */
205 /* Solaris Kerberos */
196 retval = krb5_cc_store_cred(context, ccache, *out_creds);
206 retval = krb5_cc_store_cred(context, ccache, *out_creds);
207 }
197 return retval;
198}
199
200#define INT_GC_VALIDATE 1
201#define INT_GC_RENEW 2
202
203/*ARGSUSED*/
208 return retval;
209}
210
211#define INT_GC_VALIDATE 1
212#define INT_GC_RENEW 2
213
214/*ARGSUSED*/
204static krb5_error_code
215static krb5_error_code
205krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
206 krb5_ccache ccache, krb5_creds *in_creds,
207 krb5_creds **out_creds, int which)
208{
209 krb5_error_code retval;
210 krb5_principal tmp;
211 krb5_creds **tgts = 0;
212
213 switch(which) {
214 case INT_GC_VALIDATE:
216krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
217 krb5_ccache ccache, krb5_creds *in_creds,
218 krb5_creds **out_creds, int which)
219{
220 krb5_error_code retval;
221 krb5_principal tmp;
222 krb5_creds **tgts = 0;
223
224 switch(which) {
225 case INT_GC_VALIDATE:
215 retval = krb5_get_cred_from_kdc_validate(context, ccache,
226 retval = krb5_get_cred_from_kdc_validate(context, ccache,
216 in_creds, out_creds, &tgts);
217 break;
218 case INT_GC_RENEW:
227 in_creds, out_creds, &tgts);
228 break;
229 case INT_GC_RENEW:
219 retval = krb5_get_cred_from_kdc_renew(context, ccache,
230 retval = krb5_get_cred_from_kdc_renew(context, ccache,
220 in_creds, out_creds, &tgts);
221 break;
222 default:
223 /* Should never happen */
224 retval = 255;
225 break;
226 }
227 if (retval) return retval;
228 if (tgts) krb5_free_tgt_creds(context, tgts);
229
230 retval = krb5_cc_get_principal(context, ccache, &tmp);
231 if (retval) return retval;
231 in_creds, out_creds, &tgts);
232 break;
233 default:
234 /* Should never happen */
235 retval = 255;
236 break;
237 }
238 if (retval) return retval;
239 if (tgts) krb5_free_tgt_creds(context, tgts);
240
241 retval = krb5_cc_get_principal(context, ccache, &tmp);
242 if (retval) return retval;
232
243
233 retval = krb5_cc_initialize(context, ccache, tmp);
244 retval = krb5_cc_initialize(context, ccache, tmp);
245 /* Solaris Kerberos */
234 if (retval) {
235 krb5_free_principal(context, tmp);
236 return retval;
237 }
238
239 retval = krb5_cc_store_cred(context, ccache, *out_creds);
240 krb5_free_principal(context, tmp);
241 return retval;
242}
243
244krb5_error_code KRB5_CALLCONV
245krb5_get_credentials_validate(krb5_context context, krb5_flags options,
246 krb5_ccache ccache, krb5_creds *in_creds,
247 krb5_creds **out_creds)
248{
246 if (retval) {
247 krb5_free_principal(context, tmp);
248 return retval;
249 }
250
251 retval = krb5_cc_store_cred(context, ccache, *out_creds);
252 krb5_free_principal(context, tmp);
253 return retval;
254}
255
256krb5_error_code KRB5_CALLCONV
257krb5_get_credentials_validate(krb5_context context, krb5_flags options,
258 krb5_ccache ccache, krb5_creds *in_creds,
259 krb5_creds **out_creds)
260{
249 return(krb5_get_credentials_val_renew_core(context, options, ccache,
250 in_creds, out_creds,
261 return(krb5_get_credentials_val_renew_core(context, options, ccache,
262 in_creds, out_creds,
251 INT_GC_VALIDATE));
252}
253
254krb5_error_code KRB5_CALLCONV
255krb5_get_credentials_renew(krb5_context context, krb5_flags options,
256 krb5_ccache ccache, krb5_creds *in_creds,
257 krb5_creds **out_creds)
258{
259
263 INT_GC_VALIDATE));
264}
265
266krb5_error_code KRB5_CALLCONV
267krb5_get_credentials_renew(krb5_context context, krb5_flags options,
268 krb5_ccache ccache, krb5_creds *in_creds,
269 krb5_creds **out_creds)
270{
271
260 return(krb5_get_credentials_val_renew_core(context, options, ccache,
261 in_creds, out_creds,
272 return(krb5_get_credentials_val_renew_core(context, options, ccache,
273 in_creds, out_creds,
262 INT_GC_RENEW));
263}
264
265static krb5_error_code
266krb5_validate_or_renew_creds(krb5_context context, krb5_creds *creds,
267 krb5_principal client, krb5_ccache ccache,
268 char *in_tkt_service, int validate)
269{

--- 38 unchanged lines hidden (view full) ---

308 KRB5_TGS_NAME,
309 in_creds.client->realm.length,
310 in_creds.client->realm.data,
311 0)))
312 goto cleanup;
313 }
314
315 if (validate)
274 INT_GC_RENEW));
275}
276
277static krb5_error_code
278krb5_validate_or_renew_creds(krb5_context context, krb5_creds *creds,
279 krb5_principal client, krb5_ccache ccache,
280 char *in_tkt_service, int validate)
281{

--- 38 unchanged lines hidden (view full) ---

320 KRB5_TGS_NAME,
321 in_creds.client->realm.length,
322 in_creds.client->realm.data,
323 0)))
324 goto cleanup;
325 }
326
327 if (validate)
316 ret = krb5_get_cred_from_kdc_validate(context, ccache,
328 ret = krb5_get_cred_from_kdc_validate(context, ccache,
317 &in_creds, &out_creds, &tgts);
318 else
329 &in_creds, &out_creds, &tgts);
330 else
319 ret = krb5_get_cred_from_kdc_renew(context, ccache,
331 ret = krb5_get_cred_from_kdc_renew(context, ccache,
320 &in_creds, &out_creds, &tgts);
332 &in_creds, &out_creds, &tgts);
321
333
322 /* ick. copy the struct contents, free the container */
323 if (out_creds) {
324 *creds = *out_creds;
325 krb5_xfree(out_creds);
326 }
327
328cleanup:
329

--- 21 unchanged lines hidden ---
334 /* ick. copy the struct contents, free the container */
335 if (out_creds) {
336 *creds = *out_creds;
337 krb5_xfree(out_creds);
338 }
339
340cleanup:
341

--- 21 unchanged lines hidden ---