1 /* $NetBSD: store.c,v 1.1.1.1 2011/04/13 18:15:38 elric Exp $ */ 2 3 /* 4 * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "krb5_locl.h" 37 #include "store-int.h" 38 39 #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) 40 #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) 41 #define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE) 42 #define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \ 43 krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER)) 44 45 /** 46 * Add the flags on a storage buffer by or-ing in the flags to the buffer. 47 * 48 * @param sp the storage buffer to set the flags on 49 * @param flags the flags to set 50 * 51 * @ingroup krb5_storage 52 */ 53 54 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 55 krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) 56 { 57 sp->flags |= flags; 58 } 59 60 /** 61 * Clear the flags on a storage buffer 62 * 63 * @param sp the storage buffer to clear the flags on 64 * @param flags the flags to clear 65 * 66 * @ingroup krb5_storage 67 */ 68 69 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 70 krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) 71 { 72 sp->flags &= ~flags; 73 } 74 75 /** 76 * Return true or false depending on if the storage flags is set or 77 * not. NB testing for the flag 0 always return true. 78 * 79 * @param sp the storage buffer to check flags on 80 * @param flags The flags to test for 81 * 82 * @return true if all the flags are set, false if not. 83 * 84 * @ingroup krb5_storage 85 */ 86 87 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 88 krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) 89 { 90 return (sp->flags & flags) == flags; 91 } 92 93 /** 94 * Set the new byte order of the storage buffer. 95 * 96 * @param sp the storage buffer to set the byte order for. 97 * @param byteorder the new byte order. 98 * 99 * The byte order are: KRB5_STORAGE_BYTEORDER_BE, 100 * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST. 101 * 102 * @ingroup krb5_storage 103 */ 104 105 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 106 krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder) 107 { 108 sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK; 109 sp->flags |= byteorder; 110 } 111 112 /** 113 * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants. 114 * 115 * @ingroup krb5_storage 116 */ 117 118 KRB5_LIB_FUNCTION krb5_flags KRB5_LIB_CALL 119 krb5_storage_get_byteorder(krb5_storage *sp) 120 { 121 return sp->flags & KRB5_STORAGE_BYTEORDER_MASK; 122 } 123 124 /** 125 * Seek to a new offset. 126 * 127 * @param sp the storage buffer to seek in. 128 * @param offset the offset to seek 129 * @param whence relateive searching, SEEK_CUR from the current 130 * position, SEEK_END from the end, SEEK_SET absolute from the start. 131 * 132 * @return The new current offset 133 * 134 * @ingroup krb5_storage 135 */ 136 137 KRB5_LIB_FUNCTION off_t KRB5_LIB_CALL 138 krb5_storage_seek(krb5_storage *sp, off_t offset, int whence) 139 { 140 return (*sp->seek)(sp, offset, whence); 141 } 142 143 /** 144 * Truncate the storage buffer in sp to offset. 145 * 146 * @param sp the storage buffer to truncate. 147 * @param offset the offset to truncate too. 148 * 149 * @return An Kerberos 5 error code. 150 * 151 * @ingroup krb5_storage 152 */ 153 154 KRB5_LIB_FUNCTION int KRB5_LIB_CALL 155 krb5_storage_truncate(krb5_storage *sp, off_t offset) 156 { 157 return (*sp->trunc)(sp, offset); 158 } 159 160 /** 161 * Read to the storage buffer. 162 * 163 * @param sp the storage buffer to read from 164 * @param buf the buffer to store the data in 165 * @param len the length to read 166 * 167 * @return The length of data read (can be shorter then len), or negative on error. 168 * 169 * @ingroup krb5_storage 170 */ 171 172 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL 173 krb5_storage_read(krb5_storage *sp, void *buf, size_t len) 174 { 175 return sp->fetch(sp, buf, len); 176 } 177 178 /** 179 * Write to the storage buffer. 180 * 181 * @param sp the storage buffer to write to 182 * @param buf the buffer to write to the storage buffer 183 * @param len the length to write 184 * 185 * @return The length of data written (can be shorter then len), or negative on error. 186 * 187 * @ingroup krb5_storage 188 */ 189 190 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL 191 krb5_storage_write(krb5_storage *sp, const void *buf, size_t len) 192 { 193 return sp->store(sp, buf, len); 194 } 195 196 /** 197 * Set the return code that will be used when end of storage is reached. 198 * 199 * @param sp the storage 200 * @param code the error code to return on end of storage 201 * 202 * @ingroup krb5_storage 203 */ 204 205 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 206 krb5_storage_set_eof_code(krb5_storage *sp, int code) 207 { 208 sp->eof_code = code; 209 } 210 211 /** 212 * Get the return code that will be used when end of storage is reached. 213 * 214 * @param sp the storage 215 * 216 * @return storage error code 217 * 218 * @ingroup krb5_storage 219 */ 220 221 KRB5_LIB_FUNCTION int KRB5_LIB_CALL 222 krb5_storage_get_eof_code(krb5_storage *sp) 223 { 224 return sp->eof_code; 225 } 226 227 /** 228 * Free a krb5 storage. 229 * 230 * @param sp the storage to free. 231 * 232 * @return An Kerberos 5 error code. 233 * 234 * @ingroup krb5_storage 235 */ 236 237 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 238 krb5_storage_free(krb5_storage *sp) 239 { 240 if(sp->free) 241 (*sp->free)(sp); 242 free(sp->data); 243 free(sp); 244 return 0; 245 } 246 247 /** 248 * Copy the contnent of storage 249 * 250 * @param sp the storage to copy to a data 251 * @param data the copied data, free with krb5_data_free() 252 * 253 * @return 0 for success, or a Kerberos 5 error code on failure. 254 * 255 * @ingroup krb5_storage 256 */ 257 258 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 259 krb5_storage_to_data(krb5_storage *sp, krb5_data *data) 260 { 261 off_t pos, size; 262 krb5_error_code ret; 263 264 pos = sp->seek(sp, 0, SEEK_CUR); 265 if (pos < 0) 266 return HEIM_ERR_NOT_SEEKABLE; 267 size = (size_t)sp->seek(sp, 0, SEEK_END); 268 if (size > (size_t)-1) 269 return HEIM_ERR_TOO_BIG; 270 ret = krb5_data_alloc (data, size); 271 if (ret) { 272 sp->seek(sp, pos, SEEK_SET); 273 return ret; 274 } 275 if (size) { 276 sp->seek(sp, 0, SEEK_SET); 277 sp->fetch(sp, data->data, data->length); 278 sp->seek(sp, pos, SEEK_SET); 279 } 280 return 0; 281 } 282 283 static krb5_error_code 284 krb5_store_int(krb5_storage *sp, 285 int32_t value, 286 size_t len) 287 { 288 int ret; 289 unsigned char v[16]; 290 291 if(len > sizeof(v)) 292 return EINVAL; 293 _krb5_put_int(v, value, len); 294 ret = sp->store(sp, v, len); 295 if (ret != len) 296 return (ret<0)?errno:sp->eof_code; 297 return 0; 298 } 299 300 /** 301 * Store a int32 to storage, byte order is controlled by the settings 302 * on the storage, see krb5_storage_set_byteorder(). 303 * 304 * @param sp the storage to write too 305 * @param value the value to store 306 * 307 * @return 0 for success, or a Kerberos 5 error code on failure. 308 * 309 * @ingroup krb5_storage 310 */ 311 312 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 313 krb5_store_int32(krb5_storage *sp, 314 int32_t value) 315 { 316 if(BYTEORDER_IS_HOST(sp)) 317 value = htonl(value); 318 else if(BYTEORDER_IS_LE(sp)) 319 value = bswap32(value); 320 return krb5_store_int(sp, value, 4); 321 } 322 323 /** 324 * Store a uint32 to storage, byte order is controlled by the settings 325 * on the storage, see krb5_storage_set_byteorder(). 326 * 327 * @param sp the storage to write too 328 * @param value the value to store 329 * 330 * @return 0 for success, or a Kerberos 5 error code on failure. 331 * 332 * @ingroup krb5_storage 333 */ 334 335 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 336 krb5_store_uint32(krb5_storage *sp, 337 uint32_t value) 338 { 339 return krb5_store_int32(sp, (int32_t)value); 340 } 341 342 static krb5_error_code 343 krb5_ret_int(krb5_storage *sp, 344 int32_t *value, 345 size_t len) 346 { 347 int ret; 348 unsigned char v[4]; 349 unsigned long w; 350 ret = sp->fetch(sp, v, len); 351 if(ret != len) 352 return (ret<0)?errno:sp->eof_code; 353 _krb5_get_int(v, &w, len); 354 *value = w; 355 return 0; 356 } 357 358 /** 359 * Read a int32 from storage, byte order is controlled by the settings 360 * on the storage, see krb5_storage_set_byteorder(). 361 * 362 * @param sp the storage to write too 363 * @param value the value read from the buffer 364 * 365 * @return 0 for success, or a Kerberos 5 error code on failure. 366 * 367 * @ingroup krb5_storage 368 */ 369 370 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 371 krb5_ret_int32(krb5_storage *sp, 372 int32_t *value) 373 { 374 krb5_error_code ret = krb5_ret_int(sp, value, 4); 375 if(ret) 376 return ret; 377 if(BYTEORDER_IS_HOST(sp)) 378 *value = htonl(*value); 379 else if(BYTEORDER_IS_LE(sp)) 380 *value = bswap32(*value); 381 return 0; 382 } 383 384 /** 385 * Read a uint32 from storage, byte order is controlled by the settings 386 * on the storage, see krb5_storage_set_byteorder(). 387 * 388 * @param sp the storage to write too 389 * @param value the value read from the buffer 390 * 391 * @return 0 for success, or a Kerberos 5 error code on failure. 392 * 393 * @ingroup krb5_storage 394 */ 395 396 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 397 krb5_ret_uint32(krb5_storage *sp, 398 uint32_t *value) 399 { 400 krb5_error_code ret; 401 int32_t v; 402 403 ret = krb5_ret_int32(sp, &v); 404 if (ret == 0) 405 *value = (uint32_t)v; 406 407 return ret; 408 } 409 410 /** 411 * Store a int16 to storage, byte order is controlled by the settings 412 * on the storage, see krb5_storage_set_byteorder(). 413 * 414 * @param sp the storage to write too 415 * @param value the value to store 416 * 417 * @return 0 for success, or a Kerberos 5 error code on failure. 418 * 419 * @ingroup krb5_storage 420 */ 421 422 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 423 krb5_store_int16(krb5_storage *sp, 424 int16_t value) 425 { 426 if(BYTEORDER_IS_HOST(sp)) 427 value = htons(value); 428 else if(BYTEORDER_IS_LE(sp)) 429 value = bswap16(value); 430 return krb5_store_int(sp, value, 2); 431 } 432 433 /** 434 * Store a uint16 to storage, byte order is controlled by the settings 435 * on the storage, see krb5_storage_set_byteorder(). 436 * 437 * @param sp the storage to write too 438 * @param value the value to store 439 * 440 * @return 0 for success, or a Kerberos 5 error code on failure. 441 * 442 * @ingroup krb5_storage 443 */ 444 445 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 446 krb5_store_uint16(krb5_storage *sp, 447 uint16_t value) 448 { 449 return krb5_store_int16(sp, (int16_t)value); 450 } 451 452 /** 453 * Read a int16 from storage, byte order is controlled by the settings 454 * on the storage, see krb5_storage_set_byteorder(). 455 * 456 * @param sp the storage to write too 457 * @param value the value read from the buffer 458 * 459 * @return 0 for success, or a Kerberos 5 error code on failure. 460 * 461 * @ingroup krb5_storage 462 */ 463 464 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 465 krb5_ret_int16(krb5_storage *sp, 466 int16_t *value) 467 { 468 int32_t v; 469 int ret; 470 ret = krb5_ret_int(sp, &v, 2); 471 if(ret) 472 return ret; 473 *value = v; 474 if(BYTEORDER_IS_HOST(sp)) 475 *value = htons(*value); 476 else if(BYTEORDER_IS_LE(sp)) 477 *value = bswap16(*value); 478 return 0; 479 } 480 481 /** 482 * Read a int16 from storage, byte order is controlled by the settings 483 * on the storage, see krb5_storage_set_byteorder(). 484 * 485 * @param sp the storage to write too 486 * @param value the value read from the buffer 487 * 488 * @return 0 for success, or a Kerberos 5 error code on failure. 489 * 490 * @ingroup krb5_storage 491 */ 492 493 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 494 krb5_ret_uint16(krb5_storage *sp, 495 uint16_t *value) 496 { 497 krb5_error_code ret; 498 int16_t v; 499 500 ret = krb5_ret_int16(sp, &v); 501 if (ret == 0) 502 *value = (uint16_t)v; 503 504 return ret; 505 } 506 507 /** 508 * Store a int8 to storage. 509 * 510 * @param sp the storage to write too 511 * @param value the value to store 512 * 513 * @return 0 for success, or a Kerberos 5 error code on failure. 514 * 515 * @ingroup krb5_storage 516 */ 517 518 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 519 krb5_store_int8(krb5_storage *sp, 520 int8_t value) 521 { 522 int ret; 523 524 ret = sp->store(sp, &value, sizeof(value)); 525 if (ret != sizeof(value)) 526 return (ret<0)?errno:sp->eof_code; 527 return 0; 528 } 529 530 /** 531 * Store a uint8 to storage. 532 * 533 * @param sp the storage to write too 534 * @param value the value to store 535 * 536 * @return 0 for success, or a Kerberos 5 error code on failure. 537 * 538 * @ingroup krb5_storage 539 */ 540 541 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 542 krb5_store_uint8(krb5_storage *sp, 543 uint8_t value) 544 { 545 return krb5_store_int8(sp, (int8_t)value); 546 } 547 548 /** 549 * Read a int8 from storage 550 * 551 * @param sp the storage to write too 552 * @param value the value read from the buffer 553 * 554 * @return 0 for success, or a Kerberos 5 error code on failure. 555 * 556 * @ingroup krb5_storage 557 */ 558 559 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 560 krb5_ret_int8(krb5_storage *sp, 561 int8_t *value) 562 { 563 int ret; 564 565 ret = sp->fetch(sp, value, sizeof(*value)); 566 if (ret != sizeof(*value)) 567 return (ret<0)?errno:sp->eof_code; 568 return 0; 569 } 570 571 /** 572 * Read a uint8 from storage 573 * 574 * @param sp the storage to write too 575 * @param value the value read from the buffer 576 * 577 * @return 0 for success, or a Kerberos 5 error code on failure. 578 * 579 * @ingroup krb5_storage 580 */ 581 582 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 583 krb5_ret_uint8(krb5_storage *sp, 584 uint8_t *value) 585 { 586 krb5_error_code ret; 587 int8_t v; 588 589 ret = krb5_ret_int8(sp, &v); 590 if (ret == 0) 591 *value = (uint8_t)v; 592 593 return ret; 594 } 595 596 /** 597 * Store a data to the storage. The data is stored with an int32 as 598 * lenght plus the data (not padded). 599 * 600 * @param sp the storage buffer to write to 601 * @param data the buffer to store. 602 * 603 * @return 0 on success, a Kerberos 5 error code on failure. 604 * 605 * @ingroup krb5_storage 606 */ 607 608 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 609 krb5_store_data(krb5_storage *sp, 610 krb5_data data) 611 { 612 int ret; 613 ret = krb5_store_int32(sp, data.length); 614 if(ret < 0) 615 return ret; 616 ret = sp->store(sp, data.data, data.length); 617 if(ret != data.length){ 618 if(ret < 0) 619 return errno; 620 return sp->eof_code; 621 } 622 return 0; 623 } 624 625 /** 626 * Parse a data from the storage. 627 * 628 * @param sp the storage buffer to read from 629 * @param data the parsed data 630 * 631 * @return 0 on success, a Kerberos 5 error code on failure. 632 * 633 * @ingroup krb5_storage 634 */ 635 636 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 637 krb5_ret_data(krb5_storage *sp, 638 krb5_data *data) 639 { 640 int ret; 641 int32_t size; 642 643 ret = krb5_ret_int32(sp, &size); 644 if(ret) 645 return ret; 646 ret = krb5_data_alloc (data, size); 647 if (ret) 648 return ret; 649 if (size) { 650 ret = sp->fetch(sp, data->data, size); 651 if(ret != size) 652 return (ret < 0)? errno : sp->eof_code; 653 } 654 return 0; 655 } 656 657 /** 658 * Store a string to the buffer. The data is formated as an len:uint32 659 * plus the string itself (not padded). 660 * 661 * @param sp the storage buffer to write to 662 * @param s the string to store. 663 * 664 * @return 0 on success, a Kerberos 5 error code on failure. 665 * 666 * @ingroup krb5_storage 667 */ 668 669 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 670 krb5_store_string(krb5_storage *sp, const char *s) 671 { 672 krb5_data data; 673 data.length = strlen(s); 674 data.data = rk_UNCONST(s); 675 return krb5_store_data(sp, data); 676 } 677 678 /** 679 * Parse a string from the storage. 680 * 681 * @param sp the storage buffer to read from 682 * @param string the parsed string 683 * 684 * @return 0 on success, a Kerberos 5 error code on failure. 685 * 686 * @ingroup krb5_storage 687 */ 688 689 690 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 691 krb5_ret_string(krb5_storage *sp, 692 char **string) 693 { 694 int ret; 695 krb5_data data; 696 ret = krb5_ret_data(sp, &data); 697 if(ret) 698 return ret; 699 *string = realloc(data.data, data.length + 1); 700 if(*string == NULL){ 701 free(data.data); 702 return ENOMEM; 703 } 704 (*string)[data.length] = 0; 705 return 0; 706 } 707 708 /** 709 * Store a zero terminated string to the buffer. The data is stored 710 * one character at a time until a NUL is stored. 711 * 712 * @param sp the storage buffer to write to 713 * @param s the string to store. 714 * 715 * @return 0 on success, a Kerberos 5 error code on failure. 716 * 717 * @ingroup krb5_storage 718 */ 719 720 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 721 krb5_store_stringz(krb5_storage *sp, const char *s) 722 { 723 size_t len = strlen(s) + 1; 724 ssize_t ret; 725 726 ret = sp->store(sp, s, len); 727 if(ret != len) { 728 if(ret < 0) 729 return ret; 730 else 731 return sp->eof_code; 732 } 733 return 0; 734 } 735 736 /** 737 * Parse zero terminated string from the storage. 738 * 739 * @param sp the storage buffer to read from 740 * @param string the parsed string 741 * 742 * @return 0 on success, a Kerberos 5 error code on failure. 743 * 744 * @ingroup krb5_storage 745 */ 746 747 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 748 krb5_ret_stringz(krb5_storage *sp, 749 char **string) 750 { 751 char c; 752 char *s = NULL; 753 size_t len = 0; 754 ssize_t ret; 755 756 while((ret = sp->fetch(sp, &c, 1)) == 1){ 757 char *tmp; 758 759 len++; 760 tmp = realloc (s, len); 761 if (tmp == NULL) { 762 free (s); 763 return ENOMEM; 764 } 765 s = tmp; 766 s[len - 1] = c; 767 if(c == 0) 768 break; 769 } 770 if(ret != 1){ 771 free(s); 772 if(ret == 0) 773 return sp->eof_code; 774 return ret; 775 } 776 *string = s; 777 return 0; 778 } 779 780 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 781 krb5_store_stringnl(krb5_storage *sp, const char *s) 782 { 783 size_t len = strlen(s); 784 ssize_t ret; 785 786 ret = sp->store(sp, s, len); 787 if(ret != len) { 788 if(ret < 0) 789 return ret; 790 else 791 return sp->eof_code; 792 } 793 ret = sp->store(sp, "\n", 1); 794 if(ret != 1) { 795 if(ret < 0) 796 return ret; 797 else 798 return sp->eof_code; 799 } 800 801 return 0; 802 803 } 804 805 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 806 krb5_ret_stringnl(krb5_storage *sp, 807 char **string) 808 { 809 int expect_nl = 0; 810 char c; 811 char *s = NULL; 812 size_t len = 0; 813 ssize_t ret; 814 815 while((ret = sp->fetch(sp, &c, 1)) == 1){ 816 char *tmp; 817 818 if (c == '\r') { 819 expect_nl = 1; 820 continue; 821 } 822 if (expect_nl && c != '\n') { 823 free(s); 824 return KRB5_BADMSGTYPE; 825 } 826 827 len++; 828 tmp = realloc (s, len); 829 if (tmp == NULL) { 830 free (s); 831 return ENOMEM; 832 } 833 s = tmp; 834 if(c == '\n') { 835 s[len - 1] = '\0'; 836 break; 837 } 838 s[len - 1] = c; 839 } 840 if(ret != 1){ 841 free(s); 842 if(ret == 0) 843 return sp->eof_code; 844 return ret; 845 } 846 *string = s; 847 return 0; 848 } 849 850 /** 851 * Write a principal block to storage. 852 * 853 * @param sp the storage buffer to write to 854 * @param p the principal block to write. 855 * 856 * @return 0 on success, a Kerberos 5 error code on failure. 857 * 858 * @ingroup krb5_storage 859 */ 860 861 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 862 krb5_store_principal(krb5_storage *sp, 863 krb5_const_principal p) 864 { 865 int i; 866 int ret; 867 868 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { 869 ret = krb5_store_int32(sp, p->name.name_type); 870 if(ret) return ret; 871 } 872 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 873 ret = krb5_store_int32(sp, p->name.name_string.len + 1); 874 else 875 ret = krb5_store_int32(sp, p->name.name_string.len); 876 877 if(ret) return ret; 878 ret = krb5_store_string(sp, p->realm); 879 if(ret) return ret; 880 for(i = 0; i < p->name.name_string.len; i++){ 881 ret = krb5_store_string(sp, p->name.name_string.val[i]); 882 if(ret) return ret; 883 } 884 return 0; 885 } 886 887 /** 888 * Parse principal from the storage. 889 * 890 * @param sp the storage buffer to read from 891 * @param princ the parsed principal 892 * 893 * @return 0 on success, a Kerberos 5 error code on failure. 894 * 895 * @ingroup krb5_storage 896 */ 897 898 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 899 krb5_ret_principal(krb5_storage *sp, 900 krb5_principal *princ) 901 { 902 int i; 903 int ret; 904 krb5_principal p; 905 int32_t type; 906 int32_t ncomp; 907 908 p = calloc(1, sizeof(*p)); 909 if(p == NULL) 910 return ENOMEM; 911 912 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) 913 type = KRB5_NT_UNKNOWN; 914 else if((ret = krb5_ret_int32(sp, &type))){ 915 free(p); 916 return ret; 917 } 918 if((ret = krb5_ret_int32(sp, &ncomp))){ 919 free(p); 920 return ret; 921 } 922 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 923 ncomp--; 924 if (ncomp < 0) { 925 free(p); 926 return EINVAL; 927 } 928 p->name.name_type = type; 929 p->name.name_string.len = ncomp; 930 ret = krb5_ret_string(sp, &p->realm); 931 if(ret) { 932 free(p); 933 return ret; 934 } 935 p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); 936 if(p->name.name_string.val == NULL && ncomp != 0){ 937 free(p->realm); 938 free(p); 939 return ENOMEM; 940 } 941 for(i = 0; i < ncomp; i++){ 942 ret = krb5_ret_string(sp, &p->name.name_string.val[i]); 943 if(ret) { 944 while (i >= 0) 945 free(p->name.name_string.val[i--]); 946 free(p->realm); 947 free(p); 948 return ret; 949 } 950 } 951 *princ = p; 952 return 0; 953 } 954 955 /** 956 * Store a keyblock to the storage. 957 * 958 * @param sp the storage buffer to write to 959 * @param p the keyblock to write 960 * 961 * @return 0 on success, a Kerberos 5 error code on failure. 962 * 963 * @ingroup krb5_storage 964 */ 965 966 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 967 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p) 968 { 969 int ret; 970 ret = krb5_store_int16(sp, p.keytype); 971 if(ret) return ret; 972 973 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 974 /* this should really be enctype, but it is the same as 975 keytype nowadays */ 976 ret = krb5_store_int16(sp, p.keytype); 977 if(ret) return ret; 978 } 979 980 ret = krb5_store_data(sp, p.keyvalue); 981 return ret; 982 } 983 984 /** 985 * Read a keyblock from the storage. 986 * 987 * @param sp the storage buffer to write to 988 * @param p the keyblock read from storage, free using krb5_free_keyblock() 989 * 990 * @return 0 on success, a Kerberos 5 error code on failure. 991 * 992 * @ingroup krb5_storage 993 */ 994 995 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 996 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p) 997 { 998 int ret; 999 int16_t tmp; 1000 1001 ret = krb5_ret_int16(sp, &tmp); 1002 if(ret) return ret; 1003 p->keytype = tmp; 1004 1005 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 1006 ret = krb5_ret_int16(sp, &tmp); 1007 if(ret) return ret; 1008 } 1009 1010 ret = krb5_ret_data(sp, &p->keyvalue); 1011 return ret; 1012 } 1013 1014 /** 1015 * Write a times block to storage. 1016 * 1017 * @param sp the storage buffer to write to 1018 * @param times the times block to write. 1019 * 1020 * @return 0 on success, a Kerberos 5 error code on failure. 1021 * 1022 * @ingroup krb5_storage 1023 */ 1024 1025 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1026 krb5_store_times(krb5_storage *sp, krb5_times times) 1027 { 1028 int ret; 1029 ret = krb5_store_int32(sp, times.authtime); 1030 if(ret) return ret; 1031 ret = krb5_store_int32(sp, times.starttime); 1032 if(ret) return ret; 1033 ret = krb5_store_int32(sp, times.endtime); 1034 if(ret) return ret; 1035 ret = krb5_store_int32(sp, times.renew_till); 1036 return ret; 1037 } 1038 1039 /** 1040 * Read a times block from the storage. 1041 * 1042 * @param sp the storage buffer to write to 1043 * @param times the times block read from storage 1044 * 1045 * @return 0 on success, a Kerberos 5 error code on failure. 1046 * 1047 * @ingroup krb5_storage 1048 */ 1049 1050 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1051 krb5_ret_times(krb5_storage *sp, krb5_times *times) 1052 { 1053 int ret; 1054 int32_t tmp; 1055 ret = krb5_ret_int32(sp, &tmp); 1056 times->authtime = tmp; 1057 if(ret) return ret; 1058 ret = krb5_ret_int32(sp, &tmp); 1059 times->starttime = tmp; 1060 if(ret) return ret; 1061 ret = krb5_ret_int32(sp, &tmp); 1062 times->endtime = tmp; 1063 if(ret) return ret; 1064 ret = krb5_ret_int32(sp, &tmp); 1065 times->renew_till = tmp; 1066 return ret; 1067 } 1068 1069 /** 1070 * Write a address block to storage. 1071 * 1072 * @param sp the storage buffer to write to 1073 * @param p the address block to write. 1074 * 1075 * @return 0 on success, a Kerberos 5 error code on failure. 1076 * 1077 * @ingroup krb5_storage 1078 */ 1079 1080 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1081 krb5_store_address(krb5_storage *sp, krb5_address p) 1082 { 1083 int ret; 1084 ret = krb5_store_int16(sp, p.addr_type); 1085 if(ret) return ret; 1086 ret = krb5_store_data(sp, p.address); 1087 return ret; 1088 } 1089 1090 /** 1091 * Read a address block from the storage. 1092 * 1093 * @param sp the storage buffer to write to 1094 * @param adr the address block read from storage 1095 * 1096 * @return 0 on success, a Kerberos 5 error code on failure. 1097 * 1098 * @ingroup krb5_storage 1099 */ 1100 1101 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1102 krb5_ret_address(krb5_storage *sp, krb5_address *adr) 1103 { 1104 int16_t t; 1105 int ret; 1106 ret = krb5_ret_int16(sp, &t); 1107 if(ret) return ret; 1108 adr->addr_type = t; 1109 ret = krb5_ret_data(sp, &adr->address); 1110 return ret; 1111 } 1112 1113 /** 1114 * Write a addresses block to storage. 1115 * 1116 * @param sp the storage buffer to write to 1117 * @param p the addresses block to write. 1118 * 1119 * @return 0 on success, a Kerberos 5 error code on failure. 1120 * 1121 * @ingroup krb5_storage 1122 */ 1123 1124 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1125 krb5_store_addrs(krb5_storage *sp, krb5_addresses p) 1126 { 1127 int i; 1128 int ret; 1129 ret = krb5_store_int32(sp, p.len); 1130 if(ret) return ret; 1131 for(i = 0; i<p.len; i++){ 1132 ret = krb5_store_address(sp, p.val[i]); 1133 if(ret) break; 1134 } 1135 return ret; 1136 } 1137 1138 /** 1139 * Read a addresses block from the storage. 1140 * 1141 * @param sp the storage buffer to write to 1142 * @param adr the addresses block read from storage 1143 * 1144 * @return 0 on success, a Kerberos 5 error code on failure. 1145 * 1146 * @ingroup krb5_storage 1147 */ 1148 1149 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1150 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr) 1151 { 1152 int i; 1153 int ret; 1154 int32_t tmp; 1155 1156 ret = krb5_ret_int32(sp, &tmp); 1157 if(ret) return ret; 1158 adr->len = tmp; 1159 ALLOC(adr->val, adr->len); 1160 if (adr->val == NULL && adr->len != 0) 1161 return ENOMEM; 1162 for(i = 0; i < adr->len; i++){ 1163 ret = krb5_ret_address(sp, &adr->val[i]); 1164 if(ret) break; 1165 } 1166 return ret; 1167 } 1168 1169 /** 1170 * Write a auth data block to storage. 1171 * 1172 * @param sp the storage buffer to write to 1173 * @param auth the auth data block to write. 1174 * 1175 * @return 0 on success, a Kerberos 5 error code on failure. 1176 * 1177 * @ingroup krb5_storage 1178 */ 1179 1180 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1181 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth) 1182 { 1183 krb5_error_code ret; 1184 int i; 1185 ret = krb5_store_int32(sp, auth.len); 1186 if(ret) return ret; 1187 for(i = 0; i < auth.len; i++){ 1188 ret = krb5_store_int16(sp, auth.val[i].ad_type); 1189 if(ret) break; 1190 ret = krb5_store_data(sp, auth.val[i].ad_data); 1191 if(ret) break; 1192 } 1193 return 0; 1194 } 1195 1196 /** 1197 * Read a auth data from the storage. 1198 * 1199 * @param sp the storage buffer to write to 1200 * @param auth the auth data block read from storage 1201 * 1202 * @return 0 on success, a Kerberos 5 error code on failure. 1203 * 1204 * @ingroup krb5_storage 1205 */ 1206 1207 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1208 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) 1209 { 1210 krb5_error_code ret; 1211 int32_t tmp; 1212 int16_t tmp2; 1213 int i; 1214 ret = krb5_ret_int32(sp, &tmp); 1215 if(ret) return ret; 1216 ALLOC_SEQ(auth, tmp); 1217 if (auth->val == NULL && tmp != 0) 1218 return ENOMEM; 1219 for(i = 0; i < tmp; i++){ 1220 ret = krb5_ret_int16(sp, &tmp2); 1221 if(ret) break; 1222 auth->val[i].ad_type = tmp2; 1223 ret = krb5_ret_data(sp, &auth->val[i].ad_data); 1224 if(ret) break; 1225 } 1226 return ret; 1227 } 1228 1229 static int32_t 1230 bitswap32(int32_t b) 1231 { 1232 int32_t r = 0; 1233 int i; 1234 for (i = 0; i < 32; i++) { 1235 r = r << 1 | (b & 1); 1236 b = b >> 1; 1237 } 1238 return r; 1239 } 1240 1241 /** 1242 * Write a credentials block to storage. 1243 * 1244 * @param sp the storage buffer to write to 1245 * @param creds the creds block to write. 1246 * 1247 * @return 0 on success, a Kerberos 5 error code on failure. 1248 * 1249 * @ingroup krb5_storage 1250 */ 1251 1252 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1253 krb5_store_creds(krb5_storage *sp, krb5_creds *creds) 1254 { 1255 int ret; 1256 1257 ret = krb5_store_principal(sp, creds->client); 1258 if(ret) 1259 return ret; 1260 ret = krb5_store_principal(sp, creds->server); 1261 if(ret) 1262 return ret; 1263 ret = krb5_store_keyblock(sp, creds->session); 1264 if(ret) 1265 return ret; 1266 ret = krb5_store_times(sp, creds->times); 1267 if(ret) 1268 return ret; 1269 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 1270 if(ret) 1271 return ret; 1272 1273 if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER)) 1274 ret = krb5_store_int32(sp, creds->flags.i); 1275 else 1276 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 1277 if(ret) 1278 return ret; 1279 1280 ret = krb5_store_addrs(sp, creds->addresses); 1281 if(ret) 1282 return ret; 1283 ret = krb5_store_authdata(sp, creds->authdata); 1284 if(ret) 1285 return ret; 1286 ret = krb5_store_data(sp, creds->ticket); 1287 if(ret) 1288 return ret; 1289 ret = krb5_store_data(sp, creds->second_ticket); 1290 return ret; 1291 } 1292 1293 /** 1294 * Read a credentials block from the storage. 1295 * 1296 * @param sp the storage buffer to write to 1297 * @param creds the credentials block read from storage 1298 * 1299 * @return 0 on success, a Kerberos 5 error code on failure. 1300 * 1301 * @ingroup krb5_storage 1302 */ 1303 1304 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1305 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) 1306 { 1307 krb5_error_code ret; 1308 int8_t dummy8; 1309 int32_t dummy32; 1310 1311 memset(creds, 0, sizeof(*creds)); 1312 ret = krb5_ret_principal (sp, &creds->client); 1313 if(ret) goto cleanup; 1314 ret = krb5_ret_principal (sp, &creds->server); 1315 if(ret) goto cleanup; 1316 ret = krb5_ret_keyblock (sp, &creds->session); 1317 if(ret) goto cleanup; 1318 ret = krb5_ret_times (sp, &creds->times); 1319 if(ret) goto cleanup; 1320 ret = krb5_ret_int8 (sp, &dummy8); 1321 if(ret) goto cleanup; 1322 ret = krb5_ret_int32 (sp, &dummy32); 1323 if(ret) goto cleanup; 1324 /* 1325 * Runtime detect the what is the higher bits of the bitfield. If 1326 * any of the higher bits are set in the input data, it's either a 1327 * new ticket flag (and this code need to be removed), or it's a 1328 * MIT cache (or new Heimdal cache), lets change it to our current 1329 * format. 1330 */ 1331 { 1332 uint32_t mask = 0xffff0000; 1333 creds->flags.i = 0; 1334 creds->flags.b.anonymous = 1; 1335 if (creds->flags.i & mask) 1336 mask = ~mask; 1337 if (dummy32 & mask) 1338 dummy32 = bitswap32(dummy32); 1339 } 1340 creds->flags.i = dummy32; 1341 ret = krb5_ret_addrs (sp, &creds->addresses); 1342 if(ret) goto cleanup; 1343 ret = krb5_ret_authdata (sp, &creds->authdata); 1344 if(ret) goto cleanup; 1345 ret = krb5_ret_data (sp, &creds->ticket); 1346 if(ret) goto cleanup; 1347 ret = krb5_ret_data (sp, &creds->second_ticket); 1348 cleanup: 1349 if(ret) { 1350 #if 0 1351 krb5_free_cred_contents(context, creds); /* XXX */ 1352 #endif 1353 } 1354 return ret; 1355 } 1356 1357 #define SC_CLIENT_PRINCIPAL 0x0001 1358 #define SC_SERVER_PRINCIPAL 0x0002 1359 #define SC_SESSION_KEY 0x0004 1360 #define SC_TICKET 0x0008 1361 #define SC_SECOND_TICKET 0x0010 1362 #define SC_AUTHDATA 0x0020 1363 #define SC_ADDRESSES 0x0040 1364 1365 /** 1366 * Write a tagged credentials block to storage. 1367 * 1368 * @param sp the storage buffer to write to 1369 * @param creds the creds block to write. 1370 * 1371 * @return 0 on success, a Kerberos 5 error code on failure. 1372 * 1373 * @ingroup krb5_storage 1374 */ 1375 1376 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1377 krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) 1378 { 1379 int ret; 1380 int32_t header = 0; 1381 1382 if (creds->client) 1383 header |= SC_CLIENT_PRINCIPAL; 1384 if (creds->server) 1385 header |= SC_SERVER_PRINCIPAL; 1386 if (creds->session.keytype != ETYPE_NULL) 1387 header |= SC_SESSION_KEY; 1388 if (creds->ticket.data) 1389 header |= SC_TICKET; 1390 if (creds->second_ticket.length) 1391 header |= SC_SECOND_TICKET; 1392 if (creds->authdata.len) 1393 header |= SC_AUTHDATA; 1394 if (creds->addresses.len) 1395 header |= SC_ADDRESSES; 1396 1397 ret = krb5_store_int32(sp, header); 1398 if (ret) 1399 return ret; 1400 1401 if (creds->client) { 1402 ret = krb5_store_principal(sp, creds->client); 1403 if(ret) 1404 return ret; 1405 } 1406 1407 if (creds->server) { 1408 ret = krb5_store_principal(sp, creds->server); 1409 if(ret) 1410 return ret; 1411 } 1412 1413 if (creds->session.keytype != ETYPE_NULL) { 1414 ret = krb5_store_keyblock(sp, creds->session); 1415 if(ret) 1416 return ret; 1417 } 1418 1419 ret = krb5_store_times(sp, creds->times); 1420 if(ret) 1421 return ret; 1422 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 1423 if(ret) 1424 return ret; 1425 1426 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 1427 if(ret) 1428 return ret; 1429 1430 if (creds->addresses.len) { 1431 ret = krb5_store_addrs(sp, creds->addresses); 1432 if(ret) 1433 return ret; 1434 } 1435 1436 if (creds->authdata.len) { 1437 ret = krb5_store_authdata(sp, creds->authdata); 1438 if(ret) 1439 return ret; 1440 } 1441 1442 if (creds->ticket.data) { 1443 ret = krb5_store_data(sp, creds->ticket); 1444 if(ret) 1445 return ret; 1446 } 1447 1448 if (creds->second_ticket.data) { 1449 ret = krb5_store_data(sp, creds->second_ticket); 1450 if (ret) 1451 return ret; 1452 } 1453 1454 return ret; 1455 } 1456 1457 /** 1458 * Read a tagged credentials block from the storage. 1459 * 1460 * @param sp the storage buffer to write to 1461 * @param creds the credentials block read from storage 1462 * 1463 * @return 0 on success, a Kerberos 5 error code on failure. 1464 * 1465 * @ingroup krb5_storage 1466 */ 1467 1468 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1469 krb5_ret_creds_tag(krb5_storage *sp, 1470 krb5_creds *creds) 1471 { 1472 krb5_error_code ret; 1473 int8_t dummy8; 1474 int32_t dummy32, header; 1475 1476 memset(creds, 0, sizeof(*creds)); 1477 1478 ret = krb5_ret_int32 (sp, &header); 1479 if (ret) goto cleanup; 1480 1481 if (header & SC_CLIENT_PRINCIPAL) { 1482 ret = krb5_ret_principal (sp, &creds->client); 1483 if(ret) goto cleanup; 1484 } 1485 if (header & SC_SERVER_PRINCIPAL) { 1486 ret = krb5_ret_principal (sp, &creds->server); 1487 if(ret) goto cleanup; 1488 } 1489 if (header & SC_SESSION_KEY) { 1490 ret = krb5_ret_keyblock (sp, &creds->session); 1491 if(ret) goto cleanup; 1492 } 1493 ret = krb5_ret_times (sp, &creds->times); 1494 if(ret) goto cleanup; 1495 ret = krb5_ret_int8 (sp, &dummy8); 1496 if(ret) goto cleanup; 1497 ret = krb5_ret_int32 (sp, &dummy32); 1498 if(ret) goto cleanup; 1499 /* 1500 * Runtime detect the what is the higher bits of the bitfield. If 1501 * any of the higher bits are set in the input data, it's either a 1502 * new ticket flag (and this code need to be removed), or it's a 1503 * MIT cache (or new Heimdal cache), lets change it to our current 1504 * format. 1505 */ 1506 { 1507 uint32_t mask = 0xffff0000; 1508 creds->flags.i = 0; 1509 creds->flags.b.anonymous = 1; 1510 if (creds->flags.i & mask) 1511 mask = ~mask; 1512 if (dummy32 & mask) 1513 dummy32 = bitswap32(dummy32); 1514 } 1515 creds->flags.i = dummy32; 1516 if (header & SC_ADDRESSES) { 1517 ret = krb5_ret_addrs (sp, &creds->addresses); 1518 if(ret) goto cleanup; 1519 } 1520 if (header & SC_AUTHDATA) { 1521 ret = krb5_ret_authdata (sp, &creds->authdata); 1522 if(ret) goto cleanup; 1523 } 1524 if (header & SC_TICKET) { 1525 ret = krb5_ret_data (sp, &creds->ticket); 1526 if(ret) goto cleanup; 1527 } 1528 if (header & SC_SECOND_TICKET) { 1529 ret = krb5_ret_data (sp, &creds->second_ticket); 1530 if(ret) goto cleanup; 1531 } 1532 1533 cleanup: 1534 if(ret) { 1535 #if 0 1536 krb5_free_cred_contents(context, creds); /* XXX */ 1537 #endif 1538 } 1539 return ret; 1540 } 1541