Print this page
6817447 libgss and various mechs are hiding both the real minor_status and the error token
6405422 Solaris acceptors fail in AD-KDC environments when using non-"host" services (e.g. "cifs")
6824434 Unable to accept context establishment initiated by Windows 2000 clients
6787343 kclient's site lookups fail in certain network environments
6692646 kclient should output errors to stderr
6525327 kinit failed when arcfour-hmac-md5-exp was used for the principal's key
6745582 SUNWkdcu missing package dependencies after kclientv2 integration
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c
+++ new/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c
1 1 /*
2 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2 + * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 -
7 6 /*
8 7 * Copyright 2000, 2004 by the Massachusetts Institute of Technology.
9 8 * All Rights Reserved.
10 9 *
11 10 * Export of this software from the United States of America may
12 11 * require a specific license from the United States Government.
13 12 * It is the responsibility of any person or organization contemplating
14 13 * export to obtain such a license before exporting.
15 14 *
16 15 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
17 16 * distribute this software and its documentation for any purpose and
18 17 * without fee is hereby granted, provided that the above copyright
19 18 * notice appear in all copies and that both that copyright notice and
20 19 * this permission notice appear in supporting documentation, and that
21 20 * the name of M.I.T. not be used in advertising or publicity pertaining
22 21 * to distribution of the software without specific, written prior
23 22 * permission. Furthermore if you modify this software you must label
24 23 * your software as modified software and not distribute it in such a
25 24 * fashion that it might be confused with the original M.I.T. software.
26 25 * M.I.T. makes no representations about the suitability of
27 26 * this software for any purpose. It is provided "as is" without express
28 27 * or implied warranty.
29 28 *
30 29 */
31 30 /*
32 31 * Copyright 1993 by OpenVision Technologies, Inc.
33 32 *
34 33 * Permission to use, copy, modify, distribute, and sell this software
35 34 * and its documentation for any purpose is hereby granted without fee,
36 35 * provided that the above copyright notice appears in all copies and
37 36 * that both that copyright notice and this permission notice appear in
38 37 * supporting documentation, and that the name of OpenVision not be used
39 38 * in advertising or publicity pertaining to distribution of the software
40 39 * without specific, written prior permission. OpenVision makes no
41 40 * representations about the suitability of this software for any
42 41 * purpose. It is provided "as is" without express or implied warranty.
43 42 *
44 43 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
45 44 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
46 45 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
47 46 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
48 47 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
49 48 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
50 49 * PERFORMANCE OF THIS SOFTWARE.
51 50 */
52 51
53 52 /*
54 53 * Copyright (C) 1998 by the FundsXpress, INC.
55 54 *
56 55 * All rights reserved.
57 56 *
58 57 * Export of this software from the United States of America may require
59 58 * a specific license from the United States Government. It is the
60 59 * responsibility of any person or organization contemplating export to
61 60 * obtain such a license before exporting.
62 61 *
63 62 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
64 63 * distribute this software and its documentation for any purpose and
65 64 * without fee is hereby granted, provided that the above copyright
66 65 * notice appear in all copies and that both that copyright notice and
67 66 * this permission notice appear in supporting documentation, and that
68 67 * the name of FundsXpress. not be used in advertising or publicity pertaining
69 68 * to distribution of the software without specific, written prior
70 69 * permission. FundsXpress makes no representations about the suitability of
71 70 * this software for any purpose. It is provided "as is" without express
72 71 * or implied warranty.
73 72 *
74 73 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
75 74 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
76 75 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
77 76 */
78 77
79 78 #include "k5-int.h"
80 79 #include "gssapiP_krb5.h"
81 80 #ifdef HAVE_MEMORY_H
82 81 #include <memory.h>
83 82 #endif
84 83 #include <assert.h>
85 84 #include "auth_con.h"
86 85
87 86 #ifdef CFX_EXERCISE
88 87 #define CFX_ACCEPTOR_SUBKEY (time(0) & 1)
89 88 #else
90 89 #define CFX_ACCEPTOR_SUBKEY 1
91 90 #endif
92 91
93 92 /*
94 93 * Decode, decrypt and store the forwarded creds in the local ccache.
95 94 * and populate the callers delegated credential handle if it
96 95 * was provided.
97 96 */
98 97 static krb5_error_code
99 98 rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
100 99 krb5_context context;
101 100 krb5_auth_context auth_context;
102 101 krb5_data *inbuf;
103 102 krb5_gss_cred_id_t *out_cred;
104 103 {
105 104 krb5_creds ** creds = NULL;
106 105 krb5_error_code retval;
107 106 krb5_ccache ccache = NULL;
108 107 krb5_gss_cred_id_t cred = NULL;
109 108 krb5_auth_context new_auth_ctx = NULL;
110 109 krb5_int32 flags_org;
111 110
112 111 /* Solaris Kerberos */
113 112 KRB5_LOG0(KRB5_INFO, "rd_and_store_for_creds() start");
114 113
115 114 if ((retval = krb5_auth_con_getflags(context, auth_context, &flags_org)))
116 115 return retval;
117 116 krb5_auth_con_setflags(context, auth_context,
118 117 0);
119 118
120 119 /*
121 120 * By the time krb5_rd_cred is called here (after krb5_rd_req has been
122 121 * called in krb5_gss_accept_sec_context), the "keyblock" field of
123 122 * auth_context contains a pointer to the session key, and the
124 123 * "recv_subkey" field might contain a session subkey. Either of
125 124 * these (the "recv_subkey" if it isn't NULL, otherwise the
126 125 * "keyblock") might have been used to encrypt the encrypted part of
127 126 * the KRB_CRED message that contains the forwarded credentials. (The
128 127 * Java Crypto and Security Implementation from the DSTC in Australia
129 128 * always uses the session key. But apparently it never negotiates a
130 129 * subkey, so this code works fine against a JCSI client.) Up to the
131 130 * present, though, GSSAPI clients linked against the MIT code (which
132 131 * is almost all GSSAPI clients) don't encrypt the KRB_CRED message at
133 132 * all -- at this level. So if the first call to krb5_rd_cred fails,
134 133 * we should call it a second time with another auth context freshly
135 134 * created by krb5_auth_con_init. All of its keyblock fields will be
136 135 * NULL, so krb5_rd_cred will assume that the KRB_CRED message is
137 136 * unencrypted. (The MIT code doesn't actually send the KRB_CRED
138 137 * message in the clear -- the "authenticator" whose "checksum" ends up
139 138 * containing the KRB_CRED message does get encrypted.)
140 139 */
141 140 /* Solaris Kerberos */
142 141 if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))) {
143 142 krb5_enctype enctype = ENCTYPE_NULL;
144 143 /*
145 144 * If the client is using non-DES enctypes it really ought to
146 145 * send encrypted KRB-CREDs...
147 146 */
148 147 if (auth_context->keyblock != NULL)
149 148 enctype = auth_context->keyblock->enctype;
150 149 switch (enctype) {
151 150 case ENCTYPE_DES_CBC_MD5:
152 151 case ENCTYPE_DES_CBC_CRC:
153 152 case ENCTYPE_DES3_CBC_SHA1:
154 153 break;
155 154 default:
156 155 KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
157 156 "krb5_rd_cred() retval = %d\n", retval);
158 157 goto cleanup;
159 158 /* NOTREACHED */
160 159 break;
161 160 }
162 161
163 162 /* Try to krb5_rd_cred() likely unencrypted KRB-CRED */
164 163 if ((retval = krb5_auth_con_init(context, &new_auth_ctx)))
165 164 goto cleanup;
166 165 krb5_auth_con_setflags(context, new_auth_ctx, 0);
167 166 if ((retval = krb5_rd_cred(context, new_auth_ctx, inbuf,
168 167 &creds, NULL))) {
169 168 /* Solaris Kerberos */
170 169 KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
171 170 "krb5_rd_cred() retval = %d\n", retval);
172 171 goto cleanup;
173 172 }
174 173 }
175 174
176 175 if ((retval = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) {
177 176 ccache = NULL;
178 177 goto cleanup;
179 178 }
180 179
181 180 if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client))) {
182 181 /* Solaris Kerberos */
183 182 KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
184 183 "krb5_cc_initialize() retval = %d\n", retval);
185 184 goto cleanup;
186 185 }
187 186
188 187 if ((retval = krb5_cc_store_cred(context, ccache, creds[0]))) {
189 188 /* Solaris Kerberos */
190 189 KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
191 190 "krb5_cc_store_cred() retval = %d\n", retval);
192 191 goto cleanup;
193 192 }
194 193
195 194 /* generate a delegated credential handle */
196 195 if (out_cred) {
197 196 /* allocate memory for a cred_t... */
198 197 if (!(cred =
199 198 (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
200 199 retval = ENOMEM; /* out of memory? */
201 200 *out_cred = NULL;
202 201 goto cleanup;
203 202 }
204 203
205 204 /* zero it out... */
206 205 /* Solaris Kerberos */
207 206 (void) memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
208 207
209 208 retval = k5_mutex_init(&cred->lock);
210 209 if (retval) {
211 210 xfree(cred);
212 211 cred = NULL;
213 212 goto cleanup;
214 213 }
215 214
216 215 /* copy the client principle into it... */
217 216 if ((retval =
218 217 krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
219 218 /* Solaris Kerberos */
220 219 KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
221 220 "krb5_copy_principal() retval = %d\n", retval);
222 221 k5_mutex_destroy(&cred->lock);
223 222 retval = ENOMEM; /* out of memory? */
224 223 xfree(cred); /* clean up memory on failure */
225 224 cred = NULL;
226 225 goto cleanup;
227 226 }
228 227
229 228 cred->usage = GSS_C_INITIATE; /* we can't accept with this */
230 229 /* cred->princ already set */
231 230 cred->prerfc_mech = 1; /* this cred will work with all three mechs */
232 231 cred->rfc_mech = 1;
233 232 cred->keytab = NULL; /* no keytab associated with this... */
234 233 cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
235 234 cred->ccache = ccache; /* the ccache containing the credential */
236 235 ccache = NULL; /* cred takes ownership so don't destroy */
237 236 }
238 237
239 238 /* If there were errors, there might have been a memory leak
240 239 if (!cred)
241 240 if ((retval = krb5_cc_close(context, ccache)))
242 241 goto cleanup;
243 242 */
244 243 cleanup:
245 244 if (creds)
246 245 krb5_free_tgt_creds(context, creds);
247 246
248 247 if (ccache)
249 248 (void)krb5_cc_destroy(context, ccache);
250 249
251 250 if (out_cred)
252 251 *out_cred = cred; /* return credential */
253 252
254 253 if (new_auth_ctx)
255 254 krb5_auth_con_free(context, new_auth_ctx);
256 255
257 256 krb5_auth_con_setflags(context, auth_context, flags_org);
258 257
259 258 /* Solaris Kerberos */
260 259 KRB5_LOG(KRB5_INFO, "rd_and_store_for_creds() end retval %d", retval);
261 260 return retval;
262 261 }
263 262
264 263 /*
265 264 * SUNW15resync
266 265 * Most of the logic here left "as is" because of lots of fixes MIT
267 266 * does not have yet
268 267 */
269 268 OM_uint32
270 269 krb5_gss_accept_sec_context(minor_status, context_handle,
271 270 verifier_cred_handle, input_token,
272 271 input_chan_bindings, src_name, mech_type,
273 272 output_token, ret_flags, time_rec,
274 273 delegated_cred_handle)
275 274 OM_uint32 *minor_status;
276 275 gss_ctx_id_t *context_handle;
277 276 gss_cred_id_t verifier_cred_handle;
278 277 gss_buffer_t input_token;
279 278 gss_channel_bindings_t input_chan_bindings;
280 279 gss_name_t *src_name;
281 280 gss_OID *mech_type;
282 281 gss_buffer_t output_token;
283 282 OM_uint32 *ret_flags;
284 283 OM_uint32 *time_rec;
285 284 gss_cred_id_t *delegated_cred_handle;
286 285 {
287 286 krb5_context context;
288 287 unsigned char *ptr, *ptr2;
289 288 char *sptr;
290 289 long tmp;
291 290 size_t md5len;
292 291 int bigend;
293 292 krb5_gss_cred_id_t cred = 0;
294 293 krb5_data ap_rep, ap_req;
295 294 krb5_ap_req *request = NULL;
296 295 int i;
297 296 krb5_error_code code;
298 297 krb5_address addr, *paddr;
299 298 krb5_authenticator *authdat = 0;
300 299 krb5_checksum reqcksum;
301 300 krb5_principal name = NULL;
302 301 krb5_ui_4 gss_flags = 0;
303 302 krb5_gss_ctx_id_rec *ctx = 0;
304 303 krb5_timestamp now;
305 304 gss_buffer_desc token;
306 305 krb5_auth_context auth_context = NULL;
307 306 krb5_ticket * ticket = NULL;
308 307 int option_id;
|
↓ open down ↓ |
292 lines elided |
↑ open up ↑ |
309 308 krb5_data option;
310 309 const gss_OID_desc *mech_used = NULL;
311 310 OM_uint32 major_status = GSS_S_FAILURE;
312 311 krb5_error krb_error_data;
313 312 krb5_data scratch;
314 313 gss_cred_id_t cred_handle = NULL;
315 314 krb5_gss_cred_id_t deleg_cred = NULL;
316 315 OM_uint32 saved_ap_options = 0;
317 316 krb5int_access kaccess;
318 317 int cred_rcache = 0;
318 + OM_uint32 t_minor_status = 0;
319 319
320 320 KRB5_LOG0(KRB5_INFO,"krb5_gss_accept_sec_context() start");
321 321
322 322 code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
323 323 if (code) {
324 324 *minor_status = code;
325 325 return(GSS_S_FAILURE);
326 326 }
327 327
328 328 code = krb5_gss_init_context(&context);
329 329 if (code) {
330 330 *minor_status = code;
331 331 return GSS_S_FAILURE;
332 332 }
333 333
334 334 /* set up returns to be freeable */
335 335
336 336 if (src_name)
337 337 *src_name = (gss_name_t) NULL;
338 338 output_token->length = 0;
339 339 output_token->value = NULL;
340 340 token.value = 0;
341 341 reqcksum.contents = 0;
342 342 ap_req.data = 0;
343 343 ap_rep.data = 0;
344 344
345 345 if (mech_type)
346 346 *mech_type = GSS_C_NULL_OID;
347 347 /* initialize the delegated cred handle to NO_CREDENTIAL for now */
348 348 if (delegated_cred_handle)
349 349 *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
350 350
351 351 /*
352 352 * Context handle must be unspecified. Actually, it must be
353 353 * non-established, but currently, accept_sec_context never returns
354 354 * a non-established context handle.
355 355 */
356 356 /*SUPPRESS 29*/
357 357 if (*context_handle != GSS_C_NO_CONTEXT) {
358 358 *minor_status = 0;
359 359
360 360 /* Solaris kerberos: the original Solaris code returned GSS_S_NO_CONTEXT
361 361 * for this error. This conflicts somewhat with RFC2743 which states
362 362 * GSS_S_NO_CONTEXT should be returned only for sucessor calls following
363 363 * GSS_S_CONTINUE_NEEDED status returns. Note the MIT code doesn't
364 364 * return GSS_S_NO_CONTEXT at all.
365 365 */
366 366
367 367 major_status = GSS_S_NO_CONTEXT;
368 368 KRB5_LOG0(KRB5_ERR,"krb5_gss_accept_sec_context() "
369 369 "error GSS_S_NO_CONTEXT");
370 370 goto cleanup;
371 371 }
372 372
373 373 /* verify the token's integrity, and leave the token in ap_req.
374 374 figure out which mech oid was used, and save it */
375 375
376 376 ptr = (unsigned char *) input_token->value;
377 377
378 378 if (!(code = g_verify_token_header(gss_mech_krb5,
379 379 (uint32_t *)&(ap_req.length),
380 380 &ptr, KG_TOK_CTX_AP_REQ,
381 381 input_token->length, 1))) {
382 382 mech_used = gss_mech_krb5;
383 383 } else if ((code == G_WRONG_MECH) &&
384 384 !(code = g_verify_token_header(gss_mech_krb5_old,
385 385 (uint32_t *)&(ap_req.length),
386 386 &ptr, KG_TOK_CTX_AP_REQ,
387 387 input_token->length, 1))) {
388 388 /*
389 389 * Previous versions of this library used the old mech_id
390 390 * and some broken behavior (wrong IV on checksum
391 391 * encryption). We support the old mech_id for
392 392 * compatibility, and use it to decide when to use the
393 393 * old behavior.
394 394 */
395 395 mech_used = gss_mech_krb5_old;
396 396 } else {
397 397 major_status = GSS_S_DEFECTIVE_TOKEN;
398 398 goto fail;
399 399 }
400 400
401 401 sptr = (char *) ptr;
402 402 TREAD_STR(sptr, ap_req.data, ap_req.length);
403 403
404 404 /*
405 405 * Solaris Kerberos:
406 406 * We need to decode the request now so that we can get the
407 407 * service principal in order to try and acquire a cred for it.
408 408 * below in the "handle default cred handle" code block.
409 409 */
410 410 if (!krb5_is_ap_req(&ap_req)) {
411 411 code = KRB5KRB_AP_ERR_MSG_TYPE;
412 412 goto fail;
413 413 }
414 414 /* decode the AP-REQ into request */
415 415 if ((code = decode_krb5_ap_req(&ap_req, &request))) {
416 416 if (code == KRB5_BADMSGTYPE)
417 417 code = KRB5KRB_AP_ERR_BADVERSION;
418 418 goto fail;
419 419 }
420 420
421 421 /* handle default cred handle */
422 422 /*
423 423 * Solaris Kerberos:
424 424 * If there is no princ associated with the cred then treat it the
425 425 * the same as GSS_C_NO_CREDENTIAL.
426 426 */
427 427 if (verifier_cred_handle == GSS_C_NO_CREDENTIAL ||
428 428 ((krb5_gss_cred_id_t)verifier_cred_handle)->princ == NULL) {
429 429 /* Note that we try to acquire a cred for the service principal
430 430 * named in the AP-REQ. This allows us to implement option (ii)
431 431 * of the recommended behaviour for GSS_Accept_sec_context() as
432 432 * described in section 1.1.1.3 of RFC2743.
433 433
434 434 * This is far more useful that option (i), for which we would
435 435 * acquire a cred for GSS_C_NO_NAME.
436 436 */
437 437 /* copy the princ from the ap-req or we'll lose it when we free
438 438 the ap-req */
439 439 krb5_principal princ;
440 440 if ((code = krb5_copy_principal(context, request->ticket->server,
441 441 &princ))) {
442 442 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
443 443 "krb5_copy_principal() error code %d", code);
444 444 major_status = GSS_S_FAILURE;
445 445 goto fail;
446 446 }
447 447 /* intern the acceptor name */
448 448 if (! kg_save_name((gss_name_t) princ)) {
449 449 code = G_VALIDATE_FAILED;
450 450 major_status = GSS_S_FAILURE;
451 451 goto fail;
452 452 }
453 453 major_status = krb5_gss_acquire_cred((OM_uint32*) &code,
454 454 (gss_name_t) princ,
455 455 GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
456 456 GSS_C_ACCEPT, &cred_handle,
457 457 NULL, NULL);
458 458
459 459 if (major_status != GSS_S_COMPLETE){
460 460
461 461 /* Solaris kerberos: RFC2743 indicate this should be returned if we
462 462 * can't aquire a default cred.
463 463 */
464 464 KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() "
465 465 "krb5_gss_acquire_cred() error"
466 466 "orig major_status = %d, now = GSS_S_NO_CRED\n",
467 467 major_status);
468 468
469 469 major_status = GSS_S_NO_CRED;
470 470 goto fail;
471 471 }
472 472
473 473 } else {
474 474 cred_handle = verifier_cred_handle;
475 475 }
476 476
477 477 major_status = krb5_gss_validate_cred((OM_uint32*) &code,
478 478 cred_handle);
479 479
480 480 if (GSS_ERROR(major_status)){
481 481
482 482 /* Solaris kerberos: RFC2743 indicate GSS_S_NO_CRED should be returned if
483 483 * the supplied cred isn't valid.
484 484 */
485 485
486 486 KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() "
487 487 "krb5_gss_validate_cred() error"
488 488 "orig major_status = %d, now = GSS_S_NO_CRED\n",
489 489 major_status);
490 490
491 491 major_status = GSS_S_NO_CRED;
492 492 goto fail;
493 493 }
494 494
495 495 cred = (krb5_gss_cred_id_t) cred_handle;
496 496
497 497 /* make sure the supplied credentials are valid for accept */
498 498
499 499 if ((cred->usage != GSS_C_ACCEPT) &&
500 500 (cred->usage != GSS_C_BOTH)) {
501 501 code = 0;
502 502 KRB5_LOG0(KRB5_ERR,"krb5_gss_accept_sec_context() "
503 503 "error GSS_S_NO_CONTEXT");
504 504 major_status = GSS_S_NO_CRED;
505 505 goto fail;
506 506 }
507 507
508 508 /* construct the sender_addr */
509 509
510 510 if ((input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) &&
511 511 (input_chan_bindings->initiator_addrtype == GSS_C_AF_INET)) {
512 512 /* XXX is this right? */
513 513 addr.addrtype = ADDRTYPE_INET;
514 514 addr.length = input_chan_bindings->initiator_address.length;
515 515 addr.contents = input_chan_bindings->initiator_address.value;
516 516
517 517 paddr = &addr;
518 518 } else {
519 519 paddr = NULL;
520 520 }
521 521
522 522 /* verify the AP_REQ message - setup the auth_context and rcache */
523 523
524 524 if ((code = krb5_auth_con_init(context, &auth_context))) {
525 525 major_status = GSS_S_FAILURE;
526 526 /* Solaris Kerberos */
527 527 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
528 528 "krb5_auth_con_init() error code %d", code);
529 529 goto fail;
530 530 }
531 531
532 532 (void) krb5_auth_con_setflags(context, auth_context,
533 533 KRB5_AUTH_CONTEXT_DO_SEQUENCE);
534 534
535 535 if (cred->rcache) {
536 536 cred_rcache = 1;
537 537 if ((code = krb5_auth_con_setrcache(context, auth_context, cred->rcache))) {
538 538 major_status = GSS_S_FAILURE;
539 539 /* Solaris Kerberos */
540 540 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
541 541 "krb5_auth_con_setrcache() error code %d", code);
542 542 goto fail;
543 543 }
544 544 }
545 545 if ((code = krb5_auth_con_setaddrs(context, auth_context, NULL, paddr))) {
546 546 major_status = GSS_S_FAILURE;
547 547 /* Solaris Kerberos */
548 548 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
549 549 "krb5_auth_con_setaddrs() error code %d", code);
550 550 goto fail;
551 551 }
552 552
553 553 if ((code = krb5_rd_req_decoded(context, &auth_context, request,
554 554 cred->princ, cred->keytab, NULL, &ticket))) {
555 555 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
556 556 "krb5_rd_req() error code %d", code);
557 557 if (code == KRB5_KT_KVNONOTFOUND || code == KRB5_KT_NOTFOUND) {
558 558 major_status = GSS_S_DEFECTIVE_CREDENTIAL;
559 559 code = KRB5KRB_AP_ERR_NOKEY;
560 560 }
561 561 else if (code == KRB5KRB_AP_WRONG_PRINC) {
562 562 major_status = GSS_S_NO_CRED;
563 563 code = KRB5KRB_AP_ERR_NOT_US;
564 564 }
565 565 else if (code == KRB5KRB_AP_ERR_REPEAT)
566 566 major_status = GSS_S_DUPLICATE_TOKEN;
567 567 else
568 568 major_status = GSS_S_FAILURE;
569 569 goto fail;
570 570 }
571 571 krb5_auth_con_setflags(context, auth_context,
572 572 KRB5_AUTH_CONTEXT_DO_SEQUENCE);
573 573
574 574 krb5_auth_con_getauthenticator(context, auth_context, &authdat);
575 575
576 576 #if 0
577 577 /* make sure the necessary parts of the authdat are present */
578 578
579 579 if ((authdat->authenticator->subkey == NULL) ||
580 580 (authdat->ticket->enc_part2 == NULL)) {
581 581 code = KG_NO_SUBKEY;
582 582 major_status = GSS_S_FAILURE;
583 583 goto fail;
584 584 }
585 585 #endif
586 586
587 587 {
588 588 /* gss krb5 v1 */
589 589
590 590 /* stash this now, for later. */
591 591 code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &md5len);
592 592 if (code) {
593 593 /* Solaris Kerberos */
594 594 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
595 595 "krb5_c_checksum_length() error code %d", code);
596 596 major_status = GSS_S_FAILURE;
597 597 goto fail;
598 598 }
599 599
600 600 /* verify that the checksum is correct */
601 601
602 602 /*
603 603 The checksum may be either exactly 24 bytes, in which case
604 604 no options are specified, or greater than 24 bytes, in which case
605 605 one or more options are specified. Currently, the only valid
606 606 option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ).
607 607 */
608 608
609 609 if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) ||
610 610 (authdat->checksum->length < 24)) {
611 611 code = 0;
612 612 major_status = GSS_S_BAD_BINDINGS;
613 613 goto fail;
614 614 }
615 615
616 616 /*
617 617 "Be liberal in what you accept, and
618 618 conservative in what you send"
619 619 -- rfc1123
620 620
621 621 This code will let this acceptor interoperate with an initiator
622 622 using little-endian or big-endian integer encoding.
623 623 */
624 624
625 625 ptr = (unsigned char *) authdat->checksum->contents;
626 626 bigend = 0;
627 627
628 628 TREAD_INT(ptr, tmp, bigend);
629 629
630 630 if (tmp != md5len) {
631 631 ptr = (unsigned char *) authdat->checksum->contents;
632 632 bigend = 1;
633 633
634 634 TREAD_INT(ptr, tmp, bigend);
635 635
636 636 if (tmp != md5len) {
637 637 code = KG_BAD_LENGTH;
638 638 major_status = GSS_S_FAILURE;
639 639 goto fail;
640 640 }
641 641 }
642 642
643 643 /* at this point, bigend is set according to the initiator's
644 644 byte order */
645 645
646 646
647 647 /*
648 648 The following section of code attempts to implement the
649 649 optional channel binding facility as described in RFC2743.
650 650
651 651 Since this facility is optional channel binding may or may
652 652 not have been provided by either the client or the server.
653 653
654 654 If the server has specified input_chan_bindings equal to
655 655 GSS_C_NO_CHANNEL_BINDINGS then we skip the check. If
656 656 the server does provide channel bindings then we compute
657 657 a checksum and compare against those provided by the
658 658 client. If the check fails we test the clients checksum
659 659 to see whether the client specified GSS_C_NO_CHANNEL_BINDINGS.
660 660 If either test succeeds we continue without error.
661 661 */
662 662 if ((code = kg_checksum_channel_bindings(context,
663 663 input_chan_bindings,
664 664 &reqcksum, bigend))) {
665 665 /* Solaris Kerberos */
666 666 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
667 667 "kg_checksum_channel_bindings() error code %d", code);
668 668 major_status = GSS_S_BAD_BINDINGS;
669 669 goto fail;
670 670 }
671 671
672 672 TREAD_STR(ptr, ptr2, reqcksum.length);
673 673
674 674 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS ) {
675 675 if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
676 676 xfree(reqcksum.contents);
677 677 reqcksum.contents = 0;
678 678 if ((code = kg_checksum_channel_bindings(context,
679 679 GSS_C_NO_CHANNEL_BINDINGS,
680 680 &reqcksum, bigend))) {
681 681 major_status = GSS_S_BAD_BINDINGS;
682 682 goto fail;
683 683 }
684 684 if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
685 685 code = 0;
686 686 major_status = GSS_S_BAD_BINDINGS;
687 687 goto fail;
688 688 }
689 689 }
690 690
691 691 }
692 692
693 693 TREAD_INT(ptr, gss_flags, bigend);
694 694
695 695 /* if the checksum length > 24, there are options to process */
696 696
697 697 if(authdat->checksum->length > 24 && (gss_flags & GSS_C_DELEG_FLAG)) {
698 698
699 699 i = authdat->checksum->length - 24;
700 700
701 701 if (i >= 4) {
702 702
703 703 TREAD_INT16(ptr, option_id, bigend);
704 704
705 705 TREAD_INT16(ptr, option.length, bigend);
706 706
707 707 i -= 4;
708 708
709 709 if (i < option.length || option.length < 0) {
710 710 code = KG_BAD_LENGTH;
711 711 major_status = GSS_S_FAILURE;
712 712 goto fail;
713 713 }
714 714
715 715 /* have to use ptr2, since option.data is wrong type and
716 716 macro uses ptr as both lvalue and rvalue */
717 717
718 718 TREAD_STR(ptr, ptr2, option.length);
719 719 option.data = (char *) ptr2;
720 720
721 721 i -= option.length;
722 722
723 723 if (option_id != KRB5_GSS_FOR_CREDS_OPTION) {
724 724 major_status = GSS_S_FAILURE;
725 725 goto fail;
726 726 }
727 727
728 728 /* store the delegated credential */
729 729
730 730 code = rd_and_store_for_creds(context, auth_context, &option,
731 731 (delegated_cred_handle) ?
732 732 &deleg_cred : NULL);
733 733 if (code) {
734 734 major_status = GSS_S_FAILURE;
735 735 goto fail;
736 736 }
737 737
738 738 } /* if i >= 4 */
739 739 /* ignore any additional trailing data, for now */
740 740 #ifdef CFX_EXERCISE
741 741 {
742 742 FILE *f = fopen("/tmp/gsslog", "a");
743 743 if (f) {
744 744 fprintf(f,
745 745 "initial context token with delegation, %d extra bytes\n",
746 746 i);
747 747 fclose(f);
748 748 }
749 749 }
750 750 #endif
751 751 } else {
752 752 #ifdef CFX_EXERCISE
753 753 {
754 754 FILE *f = fopen("/tmp/gsslog", "a");
755 755 if (f) {
756 756 if (gss_flags & GSS_C_DELEG_FLAG)
757 757 fprintf(f,
758 758 "initial context token, delegation flag but too small\n");
759 759 else
760 760 /* no deleg flag, length might still be too big */
761 761 fprintf(f,
762 762 "initial context token, %d extra bytes\n",
763 763 authdat->checksum->length - 24);
764 764 fclose(f);
765 765 }
766 766 }
767 767 #endif
768 768 }
769 769 }
770 770
771 771 /* create the ctx struct and start filling it in */
772 772
773 773 if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
774 774 == NULL) {
775 775 code = ENOMEM;
776 776 major_status = GSS_S_FAILURE;
777 777 goto fail;
778 778 }
779 779
780 780 memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
781 781 ctx->mech_used = (gss_OID) mech_used;
782 782 ctx->auth_context = auth_context;
783 783 ctx->initiate = 0;
784 784 ctx->gss_flags = (GSS_C_TRANS_FLAG |
785 785 ((gss_flags) & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
786 786 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
787 787 GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)));
788 788 ctx->seed_init = 0;
789 789 ctx->big_endian = bigend;
790 790 ctx->cred_rcache = cred_rcache;
791 791
792 792 /* Intern the ctx pointer so that delete_sec_context works */
793 793 if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
794 794 xfree(ctx);
795 795 ctx = 0;
796 796
797 797 /* Solaris Kerberos */
798 798 KRB5_LOG0(KRB5_ERR, "krb5_gss_accept_sec_context() "
799 799 "kg_save_ctx_id() error");
800 800 code = G_VALIDATE_FAILED;
801 801 major_status = GSS_S_FAILURE;
802 802 goto fail;
803 803 }
804 804
805 805 if ((code = krb5_copy_principal(context, cred->princ, &ctx->here))) {
806 806 /* Solaris Kerberos */
807 807 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
808 808 "krb5_copy_principal() error code %d", code);
809 809 major_status = GSS_S_FAILURE;
810 810 goto fail;
811 811 }
812 812
813 813 if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) {
814 814 /* Solaris Kerberos */
815 815 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
816 816 "krb5_copy_principal() 2 error code %d", code);
817 817 major_status = GSS_S_FAILURE;
818 818 goto fail;
819 819 }
820 820
821 821 if ((code = krb5_auth_con_getrecvsubkey(context, auth_context,
822 822 &ctx->subkey))) {
823 823 /* Solaris Kerberos */
824 824 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
825 825 "krb5_auth_con_getremotesubkey() error code %d", code);
826 826 major_status = GSS_S_FAILURE;
827 827 goto fail;
828 828 }
829 829
830 830 /* use the session key if the subkey isn't present */
831 831
832 832 if (ctx->subkey == NULL) {
833 833 if ((code = krb5_auth_con_getkey(context, auth_context,
834 834 &ctx->subkey))) {
835 835 /* Solaris Kerberos */
836 836 KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
837 837 "krb5_auth_con_getkey() error code %d", code);
838 838 *minor_status = (OM_uint32) KRB5KDC_ERR_NULL_KEY;
839 839 major_status = GSS_S_FAILURE;
840 840 goto fail;
841 841 }
842 842 }
843 843
844 844 if (ctx->subkey == NULL) {
845 845 /* this isn't a very good error, but it's not clear to me this
846 846 can actually happen */
847 847 major_status = GSS_S_FAILURE;
848 848 code = KRB5KDC_ERR_NULL_KEY;
849 849 goto fail;
850 850 }
851 851
852 852 /* Solaris Kerberos */
853 853 KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() "
854 854 "ctx->subkey->enctype=%d", ctx->subkey->enctype);
855 855
856 856 ctx->proto = 0;
857 857 switch(ctx->subkey->enctype) {
858 858 case ENCTYPE_DES_CBC_MD5:
859 859 case ENCTYPE_DES_CBC_CRC:
860 860 ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
861 861 ctx->signalg = SGN_ALG_DES_MAC_MD5;
862 862 ctx->cksum_size = 8;
863 863 ctx->sealalg = SEAL_ALG_DES;
864 864
865 865 /* fill in the encryption descriptors */
866 866
867 867 if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
868 868 major_status = GSS_S_FAILURE;
869 869 goto fail;
870 870 }
871 871
872 872 for (i=0; i<ctx->enc->length; i++)
873 873 /*SUPPRESS 113*/
874 874 ctx->enc->contents[i] ^= 0xf0;
875 875
876 876 goto copy_subkey_to_seq;
877 877 break;
878 878
879 879 case ENCTYPE_DES3_CBC_SHA1:
880 880 ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
881 881 ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
882 882 ctx->cksum_size = 20;
883 883 ctx->sealalg = SEAL_ALG_DES3KD;
884 884
885 885 /* fill in the encryption descriptors */
886 886 copy_subkey:
887 887 if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
888 888 major_status = GSS_S_FAILURE;
889 889 goto fail;
890 890 }
891 891 copy_subkey_to_seq:
892 892 if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
893 893 major_status = GSS_S_FAILURE;
894 894 goto fail;
895 895 }
896 896 break;
897 897
898 898 case ENCTYPE_ARCFOUR_HMAC:
899 899 ctx->signalg = SGN_ALG_HMAC_MD5 ;
900 900 ctx->cksum_size = 8;
901 901 ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
902 902 goto copy_subkey;
903 903
904 904 default:
905 905 ctx->signalg = -1;
906 906 ctx->sealalg = -1;
907 907 ctx->proto = 1;
908 908 code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, ctx->subkey->enctype,
909 909 &ctx->cksumtype);
910 910 if (code)
911 911 goto fail;
912 912 code = krb5_c_checksum_length(context, ctx->cksumtype,
913 913 (size_t *)&ctx->cksum_size);
914 914 if (code)
915 915 goto fail;
916 916 ctx->have_acceptor_subkey = 0;
917 917 goto copy_subkey;
918 918 }
919 919
920 920 /* Solaris Kerberos */
921 921 KRB5_LOG1(KRB5_ERR, "accept_sec_context: subkey enctype = %d proto = %d",
922 922 ctx->subkey->enctype, ctx->proto);
923 923
924 924 ctx->endtime = ticket->enc_part2->times.endtime;
925 925 ctx->krb_flags = ticket->enc_part2->flags;
926 926
927 927 krb5_free_ticket(context, ticket); /* Done with ticket */
928 928
929 929 {
930 930 krb5_ui_4 seq_temp;
931 931 krb5_auth_con_getremoteseqnumber(context, auth_context,
932 932 (krb5_int32 *)&seq_temp);
933 933 ctx->seq_recv = seq_temp;
934 934 }
935 935
936 936 if ((code = krb5_timeofday(context, &now))) {
937 937 major_status = GSS_S_FAILURE;
938 938 goto fail;
939 939 }
940 940
941 941 if (ctx->endtime < now) {
942 942 code = 0;
943 943 major_status = GSS_S_CREDENTIALS_EXPIRED;
944 944 goto fail;
945 945 }
946 946
947 947 g_order_init(&(ctx->seqstate), ctx->seq_recv,
948 948 (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
949 949 (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
950 950
951 951 /* at this point, the entire context structure is filled in,
952 952 so it can be released. */
953 953
954 954 /* generate an AP_REP if necessary */
955 955
956 956 if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
957 957 unsigned char * ptr3;
958 958 krb5_ui_4 seq_temp;
959 959 int cfx_generate_subkey;
960 960
961 961 if (ctx->proto == 1)
962 962 cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY;
963 963 else
964 964 cfx_generate_subkey = 0;
965 965
966 966 if (cfx_generate_subkey) {
967 967 krb5_int32 acflags;
968 968 code = krb5_auth_con_getflags(context, auth_context, &acflags);
969 969 if (code == 0) {
970 970 acflags |= KRB5_AUTH_CONTEXT_USE_SUBKEY;
971 971 code = krb5_auth_con_setflags(context, auth_context, acflags);
972 972 }
973 973 if (code) {
974 974 major_status = GSS_S_FAILURE;
975 975 goto fail;
976 976 }
977 977 }
978 978
979 979 if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
980 980 major_status = GSS_S_FAILURE;
981 981 goto fail;
982 982 }
983 983
984 984 krb5_auth_con_getlocalseqnumber(context, auth_context,
985 985 (krb5_int32 *)&seq_temp);
986 986 ctx->seq_send = seq_temp & 0xffffffffL;
987 987
988 988 if (cfx_generate_subkey) {
989 989 /* Get the new acceptor subkey. With the code above, there
990 990 should always be one if we make it to this point. */
991 991 code = krb5_auth_con_getsendsubkey(context, auth_context,
992 992 &ctx->acceptor_subkey);
993 993 if (code != 0) {
994 994 major_status = GSS_S_FAILURE;
995 995 goto fail;
996 996 }
997 997 code = (*kaccess.krb5int_c_mandatory_cksumtype)(context,
998 998 ctx->acceptor_subkey->enctype,
999 999 &ctx->acceptor_subkey_cksumtype);
1000 1000 if (code) {
1001 1001 major_status = GSS_S_FAILURE;
1002 1002 goto fail;
1003 1003 }
1004 1004 ctx->have_acceptor_subkey = 1;
1005 1005 }
1006 1006
1007 1007 /* the reply token hasn't been sent yet, but that's ok. */
1008 1008 ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
1009 1009 ctx->established = 1;
1010 1010
1011 1011 token.length = g_token_size(mech_used, ap_rep.length);
1012 1012
1013 1013 if ((token.value = (unsigned char *) xmalloc(token.length))
1014 1014 == NULL) {
1015 1015 major_status = GSS_S_FAILURE;
1016 1016 code = ENOMEM;
1017 1017 goto fail;
1018 1018 }
1019 1019 ptr3 = token.value;
1020 1020 g_make_token_header(mech_used, ap_rep.length,
1021 1021 &ptr3, KG_TOK_CTX_AP_REP);
1022 1022
1023 1023 TWRITE_STR(ptr3, ap_rep.data, ap_rep.length);
1024 1024
1025 1025 ctx->established = 1;
1026 1026
1027 1027 } else {
1028 1028 token.length = 0;
1029 1029 token.value = NULL;
1030 1030 ctx->seq_send = ctx->seq_recv;
1031 1031
1032 1032 ctx->established = 1;
1033 1033 }
1034 1034
1035 1035 /* set the return arguments */
1036 1036
1037 1037 if (src_name) {
1038 1038 if ((code = krb5_copy_principal(context, ctx->there, &name))) {
1039 1039 major_status = GSS_S_FAILURE;
1040 1040 goto fail;
1041 1041 }
1042 1042 /* intern the src_name */
1043 1043 if (! kg_save_name((gss_name_t) name)) {
1044 1044 code = G_VALIDATE_FAILED;
1045 1045 major_status = GSS_S_FAILURE;
1046 1046 goto fail;
1047 1047 }
1048 1048 }
1049 1049
1050 1050 if (mech_type)
1051 1051 *mech_type = (gss_OID) mech_used;
1052 1052
1053 1053 if (time_rec)
1054 1054 *time_rec = ctx->endtime - now;
1055 1055
1056 1056 if (ret_flags)
1057 1057 *ret_flags = ctx->gss_flags;
1058 1058
1059 1059 *context_handle = (gss_ctx_id_t)ctx;
1060 1060 *output_token = token;
1061 1061
1062 1062 if (src_name)
1063 1063 *src_name = (gss_name_t) name;
1064 1064
1065 1065 if (delegated_cred_handle && deleg_cred) {
1066 1066 if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
1067 1067 /* Solaris Kerberos */
1068 1068 KRB5_LOG0(KRB5_ERR, "krb5_gss_accept_sec_context() "
1069 1069 "kg_save_cred_id() error");
1070 1070 major_status = GSS_S_FAILURE;
1071 1071 code = (OM_uint32) G_VALIDATE_FAILED;
1072 1072 goto fail;
1073 1073 }
1074 1074
1075 1075 *delegated_cred_handle = (gss_cred_id_t) deleg_cred;
1076 1076 }
1077 1077
1078 1078 /* finally! */
1079 1079
1080 1080 *minor_status = 0;
1081 1081 major_status = GSS_S_COMPLETE;
1082 1082
1083 1083 fail:
1084 1084 if (authdat)
1085 1085 krb5_free_authenticator(context, authdat);
1086 1086 /* The ctx structure has the handle of the auth_context */
1087 1087 if (auth_context && !ctx) {
1088 1088 if (cred_rcache)
1089 1089 (void)krb5_auth_con_setrcache(context, auth_context, NULL);
1090 1090
1091 1091 krb5_auth_con_free(context, auth_context);
1092 1092 }
1093 1093 if (reqcksum.contents)
1094 1094 xfree(reqcksum.contents);
1095 1095 if (ap_rep.data)
1096 1096 xfree(ap_rep.data);
1097 1097
1098 1098 if (request != NULL) {
1099 1099 saved_ap_options = request->ap_options;
1100 1100 krb5_free_ap_req(context, request);
1101 1101 request = NULL;
1102 1102 }
1103 1103
1104 1104 if (!GSS_ERROR(major_status) && major_status != GSS_S_CONTINUE_NEEDED) {
1105 1105 if (!verifier_cred_handle && cred_handle) {
1106 1106 krb5_gss_release_cred(minor_status, &cred_handle);
1107 1107 }
1108 1108
1109 1109 if (ctx)
1110 1110 ctx->k5_context = context;
1111 1111
1112 1112 return(major_status);
1113 1113 }
1114 1114
1115 1115 /* from here on is the real "fail" code */
1116 1116
1117 1117 if (ctx)
1118 1118 (void) krb5_gss_delete_sec_context(minor_status,
1119 1119 (gss_ctx_id_t *) &ctx, NULL);
1120 1120 if (deleg_cred) { /* free memory associated with the deleg credential */
1121 1121 if (deleg_cred->ccache)
1122 1122 (void)krb5_cc_close(context, deleg_cred->ccache);
1123 1123 if (deleg_cred->princ)
1124 1124 krb5_free_principal(context, deleg_cred->princ);
1125 1125 xfree(deleg_cred);
1126 1126 }
1127 1127 if (token.value)
1128 1128 xfree(token.value);
1129 1129 if (name) {
1130 1130 (void) kg_delete_name((gss_name_t) name);
1131 1131 krb5_free_principal(context, name);
1132 1132 }
1133 1133
1134 1134 *minor_status = code;
1135 1135
1136 1136 if (saved_ap_options & AP_OPTS_MUTUAL_REQUIRED)
1137 1137 gss_flags |= GSS_C_MUTUAL_FLAG;
1138 1138
1139 1139 if (cred
1140 1140 && ((gss_flags & GSS_C_MUTUAL_FLAG)
1141 1141 || (major_status == GSS_S_CONTINUE_NEEDED))) {
1142 1142 unsigned int tmsglen;
1143 1143 int toktype;
1144 1144
1145 1145 /*
1146 1146 * The client is expecting a response, so we can send an
1147 1147 * error token back
1148 1148 */
1149 1149 memset(&krb_error_data, 0, sizeof(krb_error_data));
1150 1150
1151 1151 code -= ERROR_TABLE_BASE_krb5;
1152 1152 if (code < 0 || code > 128)
1153 1153 code = 60 /* KRB_ERR_GENERIC */;
1154 1154
1155 1155 krb_error_data.error = code;
1156 1156 (void) krb5_us_timeofday(context, &krb_error_data.stime,
1157 1157 &krb_error_data.susec);
1158 1158 krb_error_data.server = cred->princ;
1159 1159
1160 1160 code = krb5_mk_error(context, &krb_error_data, &scratch);
1161 1161 if (code)
1162 1162 goto cleanup;
1163 1163
1164 1164 tmsglen = scratch.length;
1165 1165 toktype = KG_TOK_CTX_ERROR;
1166 1166
1167 1167 token.length = g_token_size(mech_used, tmsglen);
1168 1168 token.value = (unsigned char *) xmalloc(token.length);
1169 1169 if (!token.value)
1170 1170 goto cleanup;
1171 1171
1172 1172 ptr = token.value;
|
↓ open down ↓ |
844 lines elided |
↑ open up ↑ |
1173 1173 g_make_token_header(mech_used, tmsglen, &ptr, toktype);
1174 1174
1175 1175 TWRITE_STR(ptr, scratch.data, scratch.length);
1176 1176 xfree(scratch.data);
1177 1177
1178 1178 *output_token = token;
1179 1179 }
1180 1180
1181 1181 cleanup:
1182 1182 if (!verifier_cred_handle && cred_handle) {
1183 - krb5_gss_release_cred(minor_status, &cred_handle);
1183 + krb5_gss_release_cred(&t_minor_status, &cred_handle);
1184 1184 }
1185 1185 krb5_free_context(context);
1186 1186
1187 1187 /* Solaris Kerberos */
1188 1188 KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() end, "
1189 1189 "major_status = %d", major_status);
1190 1190 return (major_status);
1191 1191 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX