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