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