1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 7 /* 8 * lib/gssapi/krb5/ser_sctx.c 9 * 10 * Copyright 1995, 2004 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. 17 * 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 */ 33 34 /* 35 * ser_sctx.c - Handle [de]serialization of GSSAPI security context. 36 */ 37 /* Solaris Kerberos: order is important here. include gssapiP_krb5.h 38 * before all others, otherwise we get a LINT error from MALLOC macro 39 * being redefined in mechglueP.h */ 40 #include "gssapiP_krb5.h" 41 #include "k5-int.h" 42 43 /* 44 * This module contains routines to [de]serialize 45 * krb5_gss_enc_desc and krb5_gss_ctx_id_t. 46 * XXX This whole serialization abstraction is unnecessary in a 47 * non-messaging environment, which krb5 is. Someday, this should 48 * all get redone without the extra level of indirection. I've done 49 * some of this work here, since adding new serializers is an internal 50 * krb5 interface, and I won't use those. There is some more 51 * deobfuscation (no longer anonymizing pointers, mostly) which could 52 * still be done. --marc 53 */ 54 55 /*ARGSUSED*/ 56 static krb5_error_code 57 kg_oid_externalize(kcontext, arg, buffer, lenremain) 58 krb5_context kcontext; 59 krb5_pointer arg; 60 krb5_octet **buffer; 61 size_t *lenremain; 62 { 63 gss_OID oid = (gss_OID) arg; 64 krb5_error_code err; 65 66 err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain); 67 if (err) 68 return err; 69 err = krb5_ser_pack_int32((krb5_int32) oid->length, 70 buffer, lenremain); 71 if (err) 72 return err; 73 err = krb5_ser_pack_bytes((krb5_octet *) oid->elements, 74 oid->length, buffer, lenremain); 75 if (err) 76 return err; 77 err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain); 78 return err; 79 } 80 81 /*ARGSUSED*/ 82 static krb5_error_code 83 kg_oid_internalize(kcontext, argp, buffer, lenremain) 84 krb5_context kcontext; 85 krb5_pointer *argp; 86 krb5_octet **buffer; 87 size_t *lenremain; 88 { 89 gss_OID oid; 90 krb5_int32 ibuf; 91 krb5_octet *bp; 92 size_t remain; 93 94 bp = *buffer; 95 remain = *lenremain; 96 97 /* Read in and check our magic number */ 98 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) 99 return (EINVAL); 100 101 if (ibuf != KV5M_GSS_OID) 102 return (EINVAL); 103 104 oid = (gss_OID) MALLOC(sizeof(gss_OID_desc)); 105 if (oid == NULL) 106 return ENOMEM; 107 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { 108 FREE(oid, sizeof(gss_OID_desc)); 109 return EINVAL; 110 } 111 oid->length = ibuf; 112 oid->elements = MALLOC(ibuf); 113 if (oid->elements == 0) { 114 FREE(oid, sizeof(gss_OID_desc)); 115 return ENOMEM; 116 } 117 if (krb5_ser_unpack_bytes((krb5_octet *) oid->elements, 118 oid->length, &bp, &remain)) { 119 FREE(oid->elements, oid->length); 120 FREE(oid, sizeof(gss_OID_desc)); 121 return EINVAL; 122 } 123 124 /* Read in and check our trailing magic number */ 125 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { 126 FREE(oid->elements, oid->length); 127 FREE(oid, sizeof(gss_OID_desc)); 128 return (EINVAL); 129 } 130 131 if (ibuf != KV5M_GSS_OID) { 132 FREE(oid->elements, oid->length); 133 FREE(oid, sizeof(gss_OID_desc)); 134 return (EINVAL); 135 } 136 137 *buffer = bp; 138 *lenremain = remain; 139 *argp = (krb5_pointer) oid; 140 return 0; 141 } 142 143 /*ARGSUSED*/ 144 static krb5_error_code 145 kg_oid_size(kcontext, arg, sizep) 146 krb5_context kcontext; 147 krb5_pointer arg; 148 size_t *sizep; 149 { 150 krb5_error_code kret; 151 gss_OID oid; 152 size_t required; 153 154 kret = EINVAL; 155 /*LINTED*/ 156 if ((oid = (gss_OID) arg)) { 157 required = 2*sizeof(krb5_int32); /* For the header and trailer */ 158 required += sizeof(krb5_int32); 159 required += oid->length; 160 161 kret = 0; 162 163 *sizep += required; 164 } 165 166 return(kret); 167 } 168 169 /*ARGSUSED*/ 170 static krb5_error_code 171 kg_queue_externalize(kcontext, arg, buffer, lenremain) 172 krb5_context kcontext; 173 krb5_pointer arg; 174 krb5_octet **buffer; 175 size_t *lenremain; 176 { 177 krb5_error_code err; 178 err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain); 179 if (err == 0) 180 err = g_queue_externalize(arg, buffer, lenremain); 181 if (err == 0) 182 err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain); 183 return err; 184 } 185 186 /*ARGSUSED*/ 187 static krb5_error_code 188 kg_queue_internalize(kcontext, argp, buffer, lenremain) 189 krb5_context kcontext; 190 krb5_pointer *argp; 191 krb5_octet **buffer; 192 size_t *lenremain; 193 { 194 krb5_int32 ibuf; 195 krb5_octet *bp; 196 size_t remain; 197 krb5_error_code err; 198 199 bp = *buffer; 200 remain = *lenremain; 201 202 /* Read in and check our magic number */ 203 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) 204 return (EINVAL); 205 206 if (ibuf != KV5M_GSS_QUEUE) 207 return (EINVAL); 208 209 err = g_queue_internalize(argp, &bp, &remain); 210 if (err) 211 return err; 212 213 /* Read in and check our trailing magic number */ 214 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { 215 g_order_free(argp); 216 return (EINVAL); 217 } 218 219 if (ibuf != KV5M_GSS_QUEUE) { 220 g_order_free(argp); 221 return (EINVAL); 222 } 223 224 *buffer = bp; 225 *lenremain = remain; 226 return 0; 227 } 228 229 /*ARGSUSED*/ 230 static krb5_error_code 231 kg_queue_size(kcontext, arg, sizep) 232 krb5_context kcontext; 233 krb5_pointer arg; 234 size_t *sizep; 235 { 236 krb5_error_code kret; 237 size_t required; 238 239 kret = EINVAL; 240 if (arg) { 241 required = 2*sizeof(krb5_int32); /* For the header and trailer */ 242 (void) g_queue_size(arg, &required); 243 244 kret = 0; 245 *sizep += required; 246 } 247 return(kret); 248 } 249 250 /* 251 * Determine the size required for this krb5_gss_ctx_id_rec. 252 */ 253 krb5_error_code 254 kg_ctx_size(kcontext, arg, sizep) 255 krb5_context kcontext; 256 krb5_pointer arg; 257 size_t *sizep; 258 { 259 krb5_error_code kret; 260 krb5_gss_ctx_id_rec *ctx; 261 size_t required; 262 263 /* 264 * krb5_gss_ctx_id_rec requires: 265 * krb5_int32 for KG_CONTEXT 266 * krb5_int32 for initiate. 267 * krb5_int32 for established. 268 * krb5_int32 for big_endian. 269 * krb5_int32 for have_acceptor_subkey. 270 * krb5_int32 for seed_init. 271 * krb5_int32 for gss_flags. 272 * sizeof(seed) for seed 273 * ... for here 274 * ... for there 275 * ... for subkey 276 * krb5_int32 for signalg. 277 * krb5_int32 for cksum_size. 278 * krb5_int32 for sealalg. 279 * ... for enc 280 * ... for seq 281 * krb5_int32 for endtime. 282 * krb5_int32 for flags. 283 * krb5_int64 for seq_send. 284 * krb5_int64 for seq_recv. 285 * ... for seqstate 286 * ... for auth_context 287 * ... for mech_used 288 * krb5_int32 for proto 289 * krb5_int32 for cksumtype 290 * ... for acceptor_subkey 291 * krb5_int32 for acceptor_key_cksumtype 292 * krb5_int32 for cred_rcache 293 * krb5_int32 for trailer. 294 */ 295 kret = EINVAL; 296 /*LINTED*/ 297 if ((ctx = (krb5_gss_ctx_id_rec *) arg)) { 298 required = 17*sizeof(krb5_int32); 299 required += 2*sizeof(krb5_int64); 300 required += sizeof(ctx->seed); 301 302 kret = 0; 303 if (!kret && ctx->here) 304 kret = krb5_size_opaque(kcontext, 305 KV5M_PRINCIPAL, 306 (krb5_pointer) ctx->here, 307 &required); 308 309 if (!kret && ctx->there) 310 kret = krb5_size_opaque(kcontext, 311 KV5M_PRINCIPAL, 312 (krb5_pointer) ctx->there, 313 &required); 314 315 if (!kret && ctx->subkey) 316 kret = krb5_size_opaque(kcontext, 317 KV5M_KEYBLOCK, 318 (krb5_pointer) ctx->subkey, 319 &required); 320 321 if (!kret && ctx->enc) 322 kret = krb5_size_opaque(kcontext, 323 KV5M_KEYBLOCK, 324 (krb5_pointer) ctx->enc, 325 &required); 326 327 if (!kret && ctx->seq) 328 kret = krb5_size_opaque(kcontext, 329 KV5M_KEYBLOCK, 330 (krb5_pointer) ctx->seq, 331 &required); 332 333 if (!kret) 334 kret = kg_oid_size(kcontext, 335 (krb5_pointer) ctx->mech_used, 336 &required); 337 338 if (!kret && ctx->seqstate) 339 kret = kg_queue_size(kcontext, ctx->seqstate, &required); 340 341 #ifndef PROVIDE_KERNEL_IMPORT 342 if (!kret) 343 kret = krb5_size_opaque(kcontext, 344 KV5M_CONTEXT, 345 (krb5_pointer) ctx->k5_context, 346 &required); 347 if (!kret) 348 kret = krb5_size_opaque(kcontext, 349 KV5M_AUTH_CONTEXT, 350 (krb5_pointer) ctx->auth_context, 351 &required); 352 #endif 353 354 if (!kret && ctx->acceptor_subkey) 355 kret = krb5_size_opaque(kcontext, 356 KV5M_KEYBLOCK, 357 (krb5_pointer) ctx->acceptor_subkey, 358 &required); 359 if (!kret) 360 *sizep += required; 361 } 362 return(kret); 363 } 364 365 /* 366 * Externalize this krb5_gss_ctx_id_ret. 367 */ 368 krb5_error_code 369 kg_ctx_externalize(kcontext, arg, buffer, lenremain) 370 krb5_context kcontext; 371 krb5_pointer arg; 372 krb5_octet **buffer; 373 size_t *lenremain; 374 { 375 krb5_error_code kret; 376 krb5_gss_ctx_id_rec *ctx; 377 size_t required; 378 krb5_octet *bp; 379 size_t remain; 380 #ifndef _KERNEL 381 krb5int_access kaccess; 382 383 kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); 384 if (kret) 385 return(kret); 386 #endif 387 388 required = 0; 389 bp = *buffer; 390 remain = *lenremain; 391 kret = EINVAL; 392 /*LINTED*/ 393 if ((ctx = (krb5_gss_ctx_id_rec *) arg)) { 394 kret = ENOMEM; 395 if (!kg_ctx_size(kcontext, arg, &required) && 396 (required <= remain)) { 397 /* Our identifier */ 398 (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); 399 400 /* Now static data */ 401 (void) krb5_ser_pack_int32((krb5_int32) ctx->initiate, 402 &bp, &remain); 403 (void) krb5_ser_pack_int32((krb5_int32) ctx->established, 404 &bp, &remain); 405 (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian, 406 &bp, &remain); 407 (void) krb5_ser_pack_int32((krb5_int32) ctx->have_acceptor_subkey, 408 &bp, &remain); 409 (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init, 410 &bp, &remain); 411 (void) krb5_ser_pack_int32((krb5_int32) ctx->gss_flags, 412 &bp, &remain); 413 (void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed, 414 sizeof(ctx->seed), 415 &bp, &remain); 416 (void) krb5_ser_pack_int32((krb5_int32) ctx->signalg, 417 &bp, &remain); 418 (void) krb5_ser_pack_int32((krb5_int32) ctx->cksum_size, 419 &bp, &remain); 420 (void) krb5_ser_pack_int32((krb5_int32) ctx->sealalg, 421 &bp, &remain); 422 (void) krb5_ser_pack_int32((krb5_int32) ctx->endtime, 423 &bp, &remain); 424 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_flags, 425 &bp, &remain); 426 #ifndef _KERNEL 427 (void) (*kaccess.krb5_ser_pack_int64)((krb5_int64) ctx->seq_send, 428 &bp, &remain); 429 (void) (*kaccess.krb5_ser_pack_int64)((krb5_int64) ctx->seq_recv, 430 &bp, &remain); 431 #else 432 (void) krb5_ser_pack_int64((krb5_int64) ctx->seq_send, 433 &bp, &remain); 434 (void) krb5_ser_pack_int64((krb5_int64) ctx->seq_recv, 435 &bp, &remain); 436 #endif 437 438 /* Now dynamic data */ 439 kret = 0; 440 441 if (!kret && ctx->mech_used) 442 kret = kg_oid_externalize(kcontext, ctx->mech_used, 443 &bp, &remain); 444 445 if (!kret && ctx->here) 446 kret = krb5_externalize_opaque(kcontext, 447 KV5M_PRINCIPAL, 448 (krb5_pointer) ctx->here, 449 &bp, &remain); 450 451 if (!kret && ctx->there) 452 kret = krb5_externalize_opaque(kcontext, 453 KV5M_PRINCIPAL, 454 (krb5_pointer) ctx->there, 455 &bp, &remain); 456 457 if (!kret && ctx->subkey) 458 kret = krb5_externalize_opaque(kcontext, 459 KV5M_KEYBLOCK, 460 (krb5_pointer) ctx->subkey, 461 &bp, &remain); 462 463 if (!kret && ctx->enc) 464 kret = krb5_externalize_opaque(kcontext, 465 KV5M_KEYBLOCK, 466 (krb5_pointer) ctx->enc, 467 &bp, &remain); 468 469 if (!kret && ctx->seq) 470 kret = krb5_externalize_opaque(kcontext, 471 KV5M_KEYBLOCK, 472 (krb5_pointer) ctx->seq, 473 &bp, &remain); 474 475 if (!kret && ctx->seqstate) 476 kret = kg_queue_externalize(kcontext, 477 ctx->seqstate, &bp, &remain); 478 479 #ifndef PROVIDE_KERNEL_IMPORT 480 if (!kret) 481 kret = krb5_externalize_opaque(kcontext, 482 KV5M_CONTEXT, 483 (krb5_pointer) ctx->k5_context, 484 &bp, &remain); 485 if (!kret) 486 kret = krb5_externalize_opaque(kcontext, 487 KV5M_AUTH_CONTEXT, 488 (krb5_pointer) ctx->auth_context, 489 &bp, &remain); 490 #endif 491 if (!kret) 492 kret = krb5_ser_pack_int32((krb5_int32) ctx->proto, 493 &bp, &remain); 494 if (!kret) 495 kret = krb5_ser_pack_int32((krb5_int32) ctx->cksumtype, 496 &bp, &remain); 497 if (!kret && ctx->acceptor_subkey) 498 kret = krb5_externalize_opaque(kcontext, 499 KV5M_KEYBLOCK, 500 (krb5_pointer) ctx->acceptor_subkey, 501 &bp, &remain); 502 if (!kret) 503 kret = krb5_ser_pack_int32((krb5_int32) ctx->acceptor_subkey_cksumtype, 504 &bp, &remain); 505 506 if (!kret) 507 kret = krb5_ser_pack_int32((krb5_int32) ctx->cred_rcache, 508 &bp, &remain); 509 /* trailer */ 510 if (!kret) 511 kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); 512 if (!kret) { 513 *buffer = bp; 514 *lenremain = remain; 515 } 516 } 517 } 518 return(kret); 519 } 520 521 /* 522 * Internalize this krb5_gss_ctx_id_t. 523 */ 524 krb5_error_code 525 kg_ctx_internalize(kcontext, argp, buffer, lenremain) 526 krb5_context kcontext; 527 krb5_pointer *argp; 528 krb5_octet **buffer; 529 size_t *lenremain; 530 { 531 krb5_error_code kret; 532 krb5_gss_ctx_id_rec *ctx; 533 krb5_int32 ibuf; 534 krb5_octet *bp; 535 size_t remain; 536 #ifndef _KERNEL 537 krb5int_access kaccess; 538 539 kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); 540 if (kret) 541 return(kret); 542 #endif 543 544 bp = *buffer; 545 remain = *lenremain; 546 kret = EINVAL; 547 /* Read our magic number */ 548 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) 549 ibuf = 0; 550 if (ibuf == KG_CONTEXT) { 551 kret = ENOMEM; 552 553 /* Get a context */ 554 if ((remain >= (17*sizeof(krb5_int32) 555 + 2*sizeof(krb5_int64) 556 + sizeof(ctx->seed))) && 557 (ctx = (krb5_gss_ctx_id_rec *) 558 xmalloc(sizeof(krb5_gss_ctx_id_rec)))) { 559 (void) memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); 560 561 ctx->k5_context = kcontext; 562 563 /* Get static data */ 564 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 565 ctx->initiate = (int) ibuf; 566 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 567 ctx->established = (int) ibuf; 568 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 569 ctx->big_endian = (int) ibuf; 570 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 571 ctx->have_acceptor_subkey = (int) ibuf; 572 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 573 ctx->seed_init = (int) ibuf; 574 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 575 ctx->gss_flags = (int) ibuf; 576 (void) krb5_ser_unpack_bytes((krb5_octet *) ctx->seed, 577 sizeof(ctx->seed), 578 &bp, &remain); 579 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 580 ctx->signalg = (int) ibuf; 581 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 582 ctx->cksum_size = (int) ibuf; 583 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 584 ctx->sealalg = (int) ibuf; 585 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 586 ctx->endtime = (krb5_timestamp) ibuf; 587 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 588 ctx->krb_flags = (krb5_flags) ibuf; 589 #ifndef _KERNEL 590 (void) (*kaccess.krb5_ser_unpack_int64)((krb5_int64 *)&ctx->seq_send, &bp, &remain); 591 kret = (*kaccess.krb5_ser_unpack_int64)((krb5_int64 *)&ctx->seq_recv, &bp, &remain); 592 #else 593 (void) krb5_ser_unpack_int64((krb5_int64 *) (&ctx->seq_send), 594 &bp, &remain); 595 kret = krb5_ser_unpack_int64((krb5_int64 *) (&ctx->seq_recv), 596 &bp, &remain); 597 #endif 598 if (kret) { 599 xfree_wrap(ctx, sizeof (krb5_gss_ctx_id_rec)); 600 return kret; 601 } 602 603 if ((kret = kg_oid_internalize(kcontext, 604 (krb5_pointer *) &ctx->mech_used, &bp, 605 &remain))) { 606 if (kret == EINVAL) 607 kret = 0; 608 } 609 /* Now get substructure data */ 610 if ((kret = krb5_internalize_opaque(kcontext, 611 KV5M_PRINCIPAL, 612 (krb5_pointer *) &ctx->here, 613 &bp, &remain))) { 614 if (kret == EINVAL) 615 kret = 0; 616 } 617 if (!kret && 618 (kret = krb5_internalize_opaque(kcontext, 619 KV5M_PRINCIPAL, 620 (krb5_pointer *) &ctx->there, 621 &bp, &remain))) { 622 if (kret == EINVAL) 623 kret = 0; 624 } 625 if (!kret && 626 (kret = krb5_internalize_opaque(kcontext, 627 KV5M_KEYBLOCK, 628 (krb5_pointer *) &ctx->subkey, 629 &bp, &remain))) { 630 if (kret == EINVAL) 631 kret = 0; 632 } 633 if (!kret && 634 (kret = krb5_internalize_opaque(kcontext, 635 KV5M_KEYBLOCK, 636 (krb5_pointer *) &ctx->enc, 637 &bp, &remain))) { 638 if (kret == EINVAL) 639 kret = 0; 640 } 641 if (!kret && 642 (kret = krb5_internalize_opaque(kcontext, 643 KV5M_KEYBLOCK, 644 (krb5_pointer *) &ctx->seq, 645 &bp, &remain))) { 646 if (kret == EINVAL) 647 kret = 0; 648 } 649 650 if (!kret) { 651 kret = kg_queue_internalize(kcontext, &ctx->seqstate, 652 &bp, &remain); 653 if (kret == EINVAL) 654 kret = 0; 655 } 656 657 #ifndef PROVIDE_KERNEL_IMPORT 658 if (!kret) 659 kret = krb5_internalize_opaque(kcontext, 660 KV5M_CONTEXT, 661 (krb5_pointer *) &ctx->k5_context, 662 &bp, &remain); 663 664 if (!kret) 665 kret = krb5_internalize_opaque(kcontext, 666 KV5M_AUTH_CONTEXT, 667 (krb5_pointer *) &ctx->auth_context, 668 &bp, &remain); 669 #endif 670 if (!kret) 671 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 672 ctx->proto = ibuf; 673 if (!kret) 674 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 675 ctx->cksumtype = ibuf; 676 if (!kret && 677 (kret = krb5_internalize_opaque(kcontext, 678 KV5M_KEYBLOCK, 679 (krb5_pointer *) &ctx->acceptor_subkey, 680 &bp, &remain))) { 681 if (kret == EINVAL) 682 kret = 0; 683 } 684 if (!kret) 685 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 686 ctx->cred_rcache = ibuf; 687 if (!kret) 688 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 689 ctx->acceptor_subkey_cksumtype = ibuf; 690 691 /* Get trailer */ 692 if (!kret) 693 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 694 if (!kret && ibuf != KG_CONTEXT) 695 kret = EINVAL; 696 697 if (!kret) { 698 *buffer = bp; 699 *lenremain = remain; 700 *argp = (krb5_pointer) ctx; 701 } else { 702 if (ctx->seq) 703 krb5_free_keyblock(kcontext, ctx->seq); 704 if (ctx->enc) 705 krb5_free_keyblock(kcontext, ctx->enc); 706 if (ctx->subkey) 707 krb5_free_keyblock(kcontext, ctx->subkey); 708 if (ctx->there) 709 krb5_free_principal(kcontext, ctx->there); 710 if (ctx->here) 711 krb5_free_principal(kcontext, ctx->here); 712 xfree_wrap(ctx, sizeof (krb5_gss_ctx_id_rec)); 713 } 714 } 715 } 716 return(kret); 717 } 718