1/* 2 * Copyright (c) 1997-2006 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 37RCSID("$Id: store.c 22071 2007-11-14 20:04:50Z lha $"); 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 45void KRB5_LIB_FUNCTION 46krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) 47{ 48 sp->flags |= flags; 49} 50 51void KRB5_LIB_FUNCTION 52krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) 53{ 54 sp->flags &= ~flags; 55} 56 57krb5_boolean KRB5_LIB_FUNCTION 58krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) 59{ 60 return (sp->flags & flags) == flags; 61} 62 63void KRB5_LIB_FUNCTION 64krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder) 65{ 66 sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK; 67 sp->flags |= byteorder; 68} 69 70krb5_flags KRB5_LIB_FUNCTION 71krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder) 72{ 73 return sp->flags & KRB5_STORAGE_BYTEORDER_MASK; 74} 75 76off_t KRB5_LIB_FUNCTION 77krb5_storage_seek(krb5_storage *sp, off_t offset, int whence) 78{ 79 return (*sp->seek)(sp, offset, whence); 80} 81 82krb5_ssize_t KRB5_LIB_FUNCTION 83krb5_storage_read(krb5_storage *sp, void *buf, size_t len) 84{ 85 return sp->fetch(sp, buf, len); 86} 87 88krb5_ssize_t KRB5_LIB_FUNCTION 89krb5_storage_write(krb5_storage *sp, const void *buf, size_t len) 90{ 91 return sp->store(sp, buf, len); 92} 93 94void KRB5_LIB_FUNCTION 95krb5_storage_set_eof_code(krb5_storage *sp, int code) 96{ 97 sp->eof_code = code; 98} 99 100krb5_ssize_t KRB5_LIB_FUNCTION 101_krb5_put_int(void *buffer, unsigned long value, size_t size) 102{ 103 unsigned char *p = buffer; 104 int i; 105 for (i = size - 1; i >= 0; i--) { 106 p[i] = value & 0xff; 107 value >>= 8; 108 } 109 return size; 110} 111 112krb5_ssize_t KRB5_LIB_FUNCTION 113_krb5_get_int(void *buffer, unsigned long *value, size_t size) 114{ 115 unsigned char *p = buffer; 116 unsigned long v = 0; 117 int i; 118 for (i = 0; i < size; i++) 119 v = (v << 8) + p[i]; 120 *value = v; 121 return size; 122} 123 124krb5_error_code KRB5_LIB_FUNCTION 125krb5_storage_free(krb5_storage *sp) 126{ 127 if(sp->free) 128 (*sp->free)(sp); 129 free(sp->data); 130 free(sp); 131 return 0; 132} 133 134krb5_error_code KRB5_LIB_FUNCTION 135krb5_storage_to_data(krb5_storage *sp, krb5_data *data) 136{ 137 off_t pos; 138 size_t size; 139 krb5_error_code ret; 140 141 pos = sp->seek(sp, 0, SEEK_CUR); 142 size = (size_t)sp->seek(sp, 0, SEEK_END); 143 ret = krb5_data_alloc (data, size); 144 if (ret) { 145 sp->seek(sp, pos, SEEK_SET); 146 return ret; 147 } 148 if (size) { 149 sp->seek(sp, 0, SEEK_SET); 150 sp->fetch(sp, data->data, data->length); 151 sp->seek(sp, pos, SEEK_SET); 152 } 153 return 0; 154} 155 156static krb5_error_code 157krb5_store_int(krb5_storage *sp, 158 int32_t value, 159 size_t len) 160{ 161 int ret; 162 unsigned char v[16]; 163 164 if(len > sizeof(v)) 165 return EINVAL; 166 _krb5_put_int(v, value, len); 167 ret = sp->store(sp, v, len); 168 if (ret != len) 169 return (ret<0)?errno:sp->eof_code; 170 return 0; 171} 172 173krb5_error_code KRB5_LIB_FUNCTION 174krb5_store_int32(krb5_storage *sp, 175 int32_t value) 176{ 177 if(BYTEORDER_IS_HOST(sp)) 178 value = htonl(value); 179 else if(BYTEORDER_IS_LE(sp)) 180 value = bswap32(value); 181 return krb5_store_int(sp, value, 4); 182} 183 184krb5_error_code KRB5_LIB_FUNCTION 185krb5_store_uint32(krb5_storage *sp, 186 uint32_t value) 187{ 188 return krb5_store_int32(sp, (int32_t)value); 189} 190 191static krb5_error_code 192krb5_ret_int(krb5_storage *sp, 193 int32_t *value, 194 size_t len) 195{ 196 int ret; 197 unsigned char v[4]; 198 unsigned long w; 199 ret = sp->fetch(sp, v, len); 200 if(ret != len) 201 return (ret<0)?errno:sp->eof_code; 202 _krb5_get_int(v, &w, len); 203 *value = w; 204 return 0; 205} 206 207krb5_error_code KRB5_LIB_FUNCTION 208krb5_ret_int32(krb5_storage *sp, 209 int32_t *value) 210{ 211 krb5_error_code ret = krb5_ret_int(sp, value, 4); 212 if(ret) 213 return ret; 214 if(BYTEORDER_IS_HOST(sp)) 215 *value = htonl(*value); 216 else if(BYTEORDER_IS_LE(sp)) 217 *value = bswap32(*value); 218 return 0; 219} 220 221krb5_error_code KRB5_LIB_FUNCTION 222krb5_ret_uint32(krb5_storage *sp, 223 uint32_t *value) 224{ 225 krb5_error_code ret; 226 int32_t v; 227 228 ret = krb5_ret_int32(sp, &v); 229 if (ret == 0) 230 *value = (uint32_t)v; 231 232 return ret; 233} 234 235krb5_error_code KRB5_LIB_FUNCTION 236krb5_store_int16(krb5_storage *sp, 237 int16_t value) 238{ 239 if(BYTEORDER_IS_HOST(sp)) 240 value = htons(value); 241 else if(BYTEORDER_IS_LE(sp)) 242 value = bswap16(value); 243 return krb5_store_int(sp, value, 2); 244} 245 246krb5_error_code KRB5_LIB_FUNCTION 247krb5_store_uint16(krb5_storage *sp, 248 uint16_t value) 249{ 250 return krb5_store_int16(sp, (int16_t)value); 251} 252 253krb5_error_code KRB5_LIB_FUNCTION 254krb5_ret_int16(krb5_storage *sp, 255 int16_t *value) 256{ 257 int32_t v; 258 int ret; 259 ret = krb5_ret_int(sp, &v, 2); 260 if(ret) 261 return ret; 262 *value = v; 263 if(BYTEORDER_IS_HOST(sp)) 264 *value = htons(*value); 265 else if(BYTEORDER_IS_LE(sp)) 266 *value = bswap16(*value); 267 return 0; 268} 269 270krb5_error_code KRB5_LIB_FUNCTION 271krb5_ret_uint16(krb5_storage *sp, 272 uint16_t *value) 273{ 274 krb5_error_code ret; 275 int16_t v; 276 277 ret = krb5_ret_int16(sp, &v); 278 if (ret == 0) 279 *value = (uint16_t)v; 280 281 return ret; 282} 283 284krb5_error_code KRB5_LIB_FUNCTION 285krb5_store_int8(krb5_storage *sp, 286 int8_t value) 287{ 288 int ret; 289 290 ret = sp->store(sp, &value, sizeof(value)); 291 if (ret != sizeof(value)) 292 return (ret<0)?errno:sp->eof_code; 293 return 0; 294} 295 296krb5_error_code KRB5_LIB_FUNCTION 297krb5_store_uint8(krb5_storage *sp, 298 uint8_t value) 299{ 300 return krb5_store_int8(sp, (int8_t)value); 301} 302 303krb5_error_code KRB5_LIB_FUNCTION 304krb5_ret_int8(krb5_storage *sp, 305 int8_t *value) 306{ 307 int ret; 308 309 ret = sp->fetch(sp, value, sizeof(*value)); 310 if (ret != sizeof(*value)) 311 return (ret<0)?errno:sp->eof_code; 312 return 0; 313} 314 315krb5_error_code KRB5_LIB_FUNCTION 316krb5_ret_uint8(krb5_storage *sp, 317 uint8_t *value) 318{ 319 krb5_error_code ret; 320 int8_t v; 321 322 ret = krb5_ret_int8(sp, &v); 323 if (ret == 0) 324 *value = (uint8_t)v; 325 326 return ret; 327} 328 329krb5_error_code KRB5_LIB_FUNCTION 330krb5_store_data(krb5_storage *sp, 331 krb5_data data) 332{ 333 int ret; 334 ret = krb5_store_int32(sp, data.length); 335 if(ret < 0) 336 return ret; 337 ret = sp->store(sp, data.data, data.length); 338 if(ret != data.length){ 339 if(ret < 0) 340 return errno; 341 return sp->eof_code; 342 } 343 return 0; 344} 345 346krb5_error_code KRB5_LIB_FUNCTION 347krb5_ret_data(krb5_storage *sp, 348 krb5_data *data) 349{ 350 int ret; 351 int32_t size; 352 353 ret = krb5_ret_int32(sp, &size); 354 if(ret) 355 return ret; 356 ret = krb5_data_alloc (data, size); 357 if (ret) 358 return ret; 359 if (size) { 360 ret = sp->fetch(sp, data->data, size); 361 if(ret != size) 362 return (ret < 0)? errno : sp->eof_code; 363 } 364 return 0; 365} 366 367krb5_error_code KRB5_LIB_FUNCTION 368krb5_store_string(krb5_storage *sp, const char *s) 369{ 370 krb5_data data; 371 data.length = strlen(s); 372 data.data = rk_UNCONST(s); 373 return krb5_store_data(sp, data); 374} 375 376krb5_error_code KRB5_LIB_FUNCTION 377krb5_ret_string(krb5_storage *sp, 378 char **string) 379{ 380 int ret; 381 krb5_data data; 382 ret = krb5_ret_data(sp, &data); 383 if(ret) 384 return ret; 385 *string = realloc(data.data, data.length + 1); 386 if(*string == NULL){ 387 free(data.data); 388 return ENOMEM; 389 } 390 (*string)[data.length] = 0; 391 return 0; 392} 393 394krb5_error_code KRB5_LIB_FUNCTION 395krb5_store_stringz(krb5_storage *sp, const char *s) 396{ 397 size_t len = strlen(s) + 1; 398 ssize_t ret; 399 400 ret = sp->store(sp, s, len); 401 if(ret != len) { 402 if(ret < 0) 403 return ret; 404 else 405 return sp->eof_code; 406 } 407 return 0; 408} 409 410krb5_error_code KRB5_LIB_FUNCTION 411krb5_ret_stringz(krb5_storage *sp, 412 char **string) 413{ 414 char c; 415 char *s = NULL; 416 size_t len = 0; 417 ssize_t ret; 418 419 while((ret = sp->fetch(sp, &c, 1)) == 1){ 420 char *tmp; 421 422 len++; 423 tmp = realloc (s, len); 424 if (tmp == NULL) { 425 free (s); 426 return ENOMEM; 427 } 428 s = tmp; 429 s[len - 1] = c; 430 if(c == 0) 431 break; 432 } 433 if(ret != 1){ 434 free(s); 435 if(ret == 0) 436 return sp->eof_code; 437 return ret; 438 } 439 *string = s; 440 return 0; 441} 442 443krb5_error_code KRB5_LIB_FUNCTION 444krb5_store_stringnl(krb5_storage *sp, const char *s) 445{ 446 size_t len = strlen(s); 447 ssize_t ret; 448 449 ret = sp->store(sp, s, len); 450 if(ret != len) { 451 if(ret < 0) 452 return ret; 453 else 454 return sp->eof_code; 455 } 456 ret = sp->store(sp, "\n", 1); 457 if(ret != 1) { 458 if(ret < 0) 459 return ret; 460 else 461 return sp->eof_code; 462 } 463 464 return 0; 465 466} 467 468krb5_error_code KRB5_LIB_FUNCTION 469krb5_ret_stringnl(krb5_storage *sp, 470 char **string) 471{ 472 int expect_nl = 0; 473 char c; 474 char *s = NULL; 475 size_t len = 0; 476 ssize_t ret; 477 478 while((ret = sp->fetch(sp, &c, 1)) == 1){ 479 char *tmp; 480 481 if (c == '\r') { 482 expect_nl = 1; 483 continue; 484 } 485 if (expect_nl && c != '\n') { 486 free(s); 487 return KRB5_BADMSGTYPE; 488 } 489 490 len++; 491 tmp = realloc (s, len); 492 if (tmp == NULL) { 493 free (s); 494 return ENOMEM; 495 } 496 s = tmp; 497 if(c == '\n') { 498 s[len - 1] = '\0'; 499 break; 500 } 501 s[len - 1] = c; 502 } 503 if(ret != 1){ 504 free(s); 505 if(ret == 0) 506 return sp->eof_code; 507 return ret; 508 } 509 *string = s; 510 return 0; 511} 512 513 514krb5_error_code KRB5_LIB_FUNCTION 515krb5_store_principal(krb5_storage *sp, 516 krb5_const_principal p) 517{ 518 int i; 519 int ret; 520 521 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { 522 ret = krb5_store_int32(sp, p->name.name_type); 523 if(ret) return ret; 524 } 525 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 526 ret = krb5_store_int32(sp, p->name.name_string.len + 1); 527 else 528 ret = krb5_store_int32(sp, p->name.name_string.len); 529 530 if(ret) return ret; 531 ret = krb5_store_string(sp, p->realm); 532 if(ret) return ret; 533 for(i = 0; i < p->name.name_string.len; i++){ 534 ret = krb5_store_string(sp, p->name.name_string.val[i]); 535 if(ret) return ret; 536 } 537 return 0; 538} 539 540krb5_error_code KRB5_LIB_FUNCTION 541krb5_ret_principal(krb5_storage *sp, 542 krb5_principal *princ) 543{ 544 int i; 545 int ret; 546 krb5_principal p; 547 int32_t type; 548 int32_t ncomp; 549 550 p = calloc(1, sizeof(*p)); 551 if(p == NULL) 552 return ENOMEM; 553 554 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) 555 type = KRB5_NT_UNKNOWN; 556 else if((ret = krb5_ret_int32(sp, &type))){ 557 free(p); 558 return ret; 559 } 560 if((ret = krb5_ret_int32(sp, &ncomp))){ 561 free(p); 562 return ret; 563 } 564 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 565 ncomp--; 566 if (ncomp < 0) { 567 free(p); 568 return EINVAL; 569 } 570 p->name.name_type = type; 571 p->name.name_string.len = ncomp; 572 ret = krb5_ret_string(sp, &p->realm); 573 if(ret) { 574 free(p); 575 return ret; 576 } 577 p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); 578 if(p->name.name_string.val == NULL && ncomp != 0){ 579 free(p->realm); 580 free(p); 581 return ENOMEM; 582 } 583 for(i = 0; i < ncomp; i++){ 584 ret = krb5_ret_string(sp, &p->name.name_string.val[i]); 585 if(ret) { 586 while (i >= 0) 587 free(p->name.name_string.val[i--]); 588 free(p->realm); 589 free(p); 590 return ret; 591 } 592 } 593 *princ = p; 594 return 0; 595} 596 597krb5_error_code KRB5_LIB_FUNCTION 598krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p) 599{ 600 int ret; 601 ret = krb5_store_int16(sp, p.keytype); 602 if(ret) return ret; 603 604 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 605 /* this should really be enctype, but it is the same as 606 keytype nowadays */ 607 ret = krb5_store_int16(sp, p.keytype); 608 if(ret) return ret; 609 } 610 611 ret = krb5_store_data(sp, p.keyvalue); 612 return ret; 613} 614 615krb5_error_code KRB5_LIB_FUNCTION 616krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p) 617{ 618 int ret; 619 int16_t tmp; 620 621 ret = krb5_ret_int16(sp, &tmp); 622 if(ret) return ret; 623 p->keytype = tmp; 624 625 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 626 ret = krb5_ret_int16(sp, &tmp); 627 if(ret) return ret; 628 } 629 630 ret = krb5_ret_data(sp, &p->keyvalue); 631 return ret; 632} 633 634krb5_error_code KRB5_LIB_FUNCTION 635krb5_store_times(krb5_storage *sp, krb5_times times) 636{ 637 int ret; 638 ret = krb5_store_int32(sp, times.authtime); 639 if(ret) return ret; 640 ret = krb5_store_int32(sp, times.starttime); 641 if(ret) return ret; 642 ret = krb5_store_int32(sp, times.endtime); 643 if(ret) return ret; 644 ret = krb5_store_int32(sp, times.renew_till); 645 return ret; 646} 647 648krb5_error_code KRB5_LIB_FUNCTION 649krb5_ret_times(krb5_storage *sp, krb5_times *times) 650{ 651 int ret; 652 int32_t tmp; 653 ret = krb5_ret_int32(sp, &tmp); 654 times->authtime = tmp; 655 if(ret) return ret; 656 ret = krb5_ret_int32(sp, &tmp); 657 times->starttime = tmp; 658 if(ret) return ret; 659 ret = krb5_ret_int32(sp, &tmp); 660 times->endtime = tmp; 661 if(ret) return ret; 662 ret = krb5_ret_int32(sp, &tmp); 663 times->renew_till = tmp; 664 return ret; 665} 666 667krb5_error_code KRB5_LIB_FUNCTION 668krb5_store_address(krb5_storage *sp, krb5_address p) 669{ 670 int ret; 671 ret = krb5_store_int16(sp, p.addr_type); 672 if(ret) return ret; 673 ret = krb5_store_data(sp, p.address); 674 return ret; 675} 676 677krb5_error_code KRB5_LIB_FUNCTION 678krb5_ret_address(krb5_storage *sp, krb5_address *adr) 679{ 680 int16_t t; 681 int ret; 682 ret = krb5_ret_int16(sp, &t); 683 if(ret) return ret; 684 adr->addr_type = t; 685 ret = krb5_ret_data(sp, &adr->address); 686 return ret; 687} 688 689krb5_error_code KRB5_LIB_FUNCTION 690krb5_store_addrs(krb5_storage *sp, krb5_addresses p) 691{ 692 int i; 693 int ret; 694 ret = krb5_store_int32(sp, p.len); 695 if(ret) return ret; 696 for(i = 0; i<p.len; i++){ 697 ret = krb5_store_address(sp, p.val[i]); 698 if(ret) break; 699 } 700 return ret; 701} 702 703krb5_error_code KRB5_LIB_FUNCTION 704krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr) 705{ 706 int i; 707 int ret; 708 int32_t tmp; 709 710 ret = krb5_ret_int32(sp, &tmp); 711 if(ret) return ret; 712 adr->len = tmp; 713 ALLOC(adr->val, adr->len); 714 if (adr->val == NULL && adr->len != 0) 715 return ENOMEM; 716 for(i = 0; i < adr->len; i++){ 717 ret = krb5_ret_address(sp, &adr->val[i]); 718 if(ret) break; 719 } 720 return ret; 721} 722 723krb5_error_code KRB5_LIB_FUNCTION 724krb5_store_authdata(krb5_storage *sp, krb5_authdata auth) 725{ 726 krb5_error_code ret; 727 int i; 728 ret = krb5_store_int32(sp, auth.len); 729 if(ret) return ret; 730 for(i = 0; i < auth.len; i++){ 731 ret = krb5_store_int16(sp, auth.val[i].ad_type); 732 if(ret) break; 733 ret = krb5_store_data(sp, auth.val[i].ad_data); 734 if(ret) break; 735 } 736 return 0; 737} 738 739krb5_error_code KRB5_LIB_FUNCTION 740krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) 741{ 742 krb5_error_code ret; 743 int32_t tmp; 744 int16_t tmp2; 745 int i; 746 ret = krb5_ret_int32(sp, &tmp); 747 if(ret) return ret; 748 ALLOC_SEQ(auth, tmp); 749 if (auth->val == NULL && tmp != 0) 750 return ENOMEM; 751 for(i = 0; i < tmp; i++){ 752 ret = krb5_ret_int16(sp, &tmp2); 753 if(ret) break; 754 auth->val[i].ad_type = tmp2; 755 ret = krb5_ret_data(sp, &auth->val[i].ad_data); 756 if(ret) break; 757 } 758 return ret; 759} 760 761static int32_t 762bitswap32(int32_t b) 763{ 764 int32_t r = 0; 765 int i; 766 for (i = 0; i < 32; i++) { 767 r = r << 1 | (b & 1); 768 b = b >> 1; 769 } 770 return r; 771} 772 773 774/* 775 * 776 */ 777 778krb5_error_code KRB5_LIB_FUNCTION 779krb5_store_creds(krb5_storage *sp, krb5_creds *creds) 780{ 781 int ret; 782 783 ret = krb5_store_principal(sp, creds->client); 784 if(ret) 785 return ret; 786 ret = krb5_store_principal(sp, creds->server); 787 if(ret) 788 return ret; 789 ret = krb5_store_keyblock(sp, creds->session); 790 if(ret) 791 return ret; 792 ret = krb5_store_times(sp, creds->times); 793 if(ret) 794 return ret; 795 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 796 if(ret) 797 return ret; 798 799 if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER)) 800 ret = krb5_store_int32(sp, creds->flags.i); 801 else 802 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 803 if(ret) 804 return ret; 805 806 ret = krb5_store_addrs(sp, creds->addresses); 807 if(ret) 808 return ret; 809 ret = krb5_store_authdata(sp, creds->authdata); 810 if(ret) 811 return ret; 812 ret = krb5_store_data(sp, creds->ticket); 813 if(ret) 814 return ret; 815 ret = krb5_store_data(sp, creds->second_ticket); 816 return ret; 817} 818 819krb5_error_code KRB5_LIB_FUNCTION 820krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) 821{ 822 krb5_error_code ret; 823 int8_t dummy8; 824 int32_t dummy32; 825 826 memset(creds, 0, sizeof(*creds)); 827 ret = krb5_ret_principal (sp, &creds->client); 828 if(ret) goto cleanup; 829 ret = krb5_ret_principal (sp, &creds->server); 830 if(ret) goto cleanup; 831 ret = krb5_ret_keyblock (sp, &creds->session); 832 if(ret) goto cleanup; 833 ret = krb5_ret_times (sp, &creds->times); 834 if(ret) goto cleanup; 835 ret = krb5_ret_int8 (sp, &dummy8); 836 if(ret) goto cleanup; 837 ret = krb5_ret_int32 (sp, &dummy32); 838 if(ret) goto cleanup; 839 /* 840 * Runtime detect the what is the higher bits of the bitfield. If 841 * any of the higher bits are set in the input data, it's either a 842 * new ticket flag (and this code need to be removed), or it's a 843 * MIT cache (or new Heimdal cache), lets change it to our current 844 * format. 845 */ 846 { 847 uint32_t mask = 0xffff0000; 848 creds->flags.i = 0; 849 creds->flags.b.anonymous = 1; 850 if (creds->flags.i & mask) 851 mask = ~mask; 852 if (dummy32 & mask) 853 dummy32 = bitswap32(dummy32); 854 } 855 creds->flags.i = dummy32; 856 ret = krb5_ret_addrs (sp, &creds->addresses); 857 if(ret) goto cleanup; 858 ret = krb5_ret_authdata (sp, &creds->authdata); 859 if(ret) goto cleanup; 860 ret = krb5_ret_data (sp, &creds->ticket); 861 if(ret) goto cleanup; 862 ret = krb5_ret_data (sp, &creds->second_ticket); 863cleanup: 864 if(ret) { 865#if 0 866 krb5_free_cred_contents(context, creds); /* XXX */ 867#endif 868 } 869 return ret; 870} 871 872#define SC_CLIENT_PRINCIPAL 0x0001 873#define SC_SERVER_PRINCIPAL 0x0002 874#define SC_SESSION_KEY 0x0004 875#define SC_TICKET 0x0008 876#define SC_SECOND_TICKET 0x0010 877#define SC_AUTHDATA 0x0020 878#define SC_ADDRESSES 0x0040 879 880/* 881 * 882 */ 883 884krb5_error_code KRB5_LIB_FUNCTION 885krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) 886{ 887 int ret; 888 int32_t header = 0; 889 890 if (creds->client) 891 header |= SC_CLIENT_PRINCIPAL; 892 if (creds->server) 893 header |= SC_SERVER_PRINCIPAL; 894 if (creds->session.keytype != ETYPE_NULL) 895 header |= SC_SESSION_KEY; 896 if (creds->ticket.data) 897 header |= SC_TICKET; 898 if (creds->second_ticket.length) 899 header |= SC_SECOND_TICKET; 900 if (creds->authdata.len) 901 header |= SC_AUTHDATA; 902 if (creds->addresses.len) 903 header |= SC_ADDRESSES; 904 905 ret = krb5_store_int32(sp, header); 906 907 if (creds->client) { 908 ret = krb5_store_principal(sp, creds->client); 909 if(ret) 910 return ret; 911 } 912 913 if (creds->server) { 914 ret = krb5_store_principal(sp, creds->server); 915 if(ret) 916 return ret; 917 } 918 919 if (creds->session.keytype != ETYPE_NULL) { 920 ret = krb5_store_keyblock(sp, creds->session); 921 if(ret) 922 return ret; 923 } 924 925 ret = krb5_store_times(sp, creds->times); 926 if(ret) 927 return ret; 928 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 929 if(ret) 930 return ret; 931 932 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 933 if(ret) 934 return ret; 935 936 if (creds->addresses.len) { 937 ret = krb5_store_addrs(sp, creds->addresses); 938 if(ret) 939 return ret; 940 } 941 942 if (creds->authdata.len) { 943 ret = krb5_store_authdata(sp, creds->authdata); 944 if(ret) 945 return ret; 946 } 947 948 if (creds->ticket.data) { 949 ret = krb5_store_data(sp, creds->ticket); 950 if(ret) 951 return ret; 952 } 953 954 if (creds->second_ticket.data) { 955 ret = krb5_store_data(sp, creds->second_ticket); 956 if (ret) 957 return ret; 958 } 959 960 return ret; 961} 962 963krb5_error_code KRB5_LIB_FUNCTION 964krb5_ret_creds_tag(krb5_storage *sp, 965 krb5_creds *creds) 966{ 967 krb5_error_code ret; 968 int8_t dummy8; 969 int32_t dummy32, header; 970 971 memset(creds, 0, sizeof(*creds)); 972 973 ret = krb5_ret_int32 (sp, &header); 974 if (ret) goto cleanup; 975 976 if (header & SC_CLIENT_PRINCIPAL) { 977 ret = krb5_ret_principal (sp, &creds->client); 978 if(ret) goto cleanup; 979 } 980 if (header & SC_SERVER_PRINCIPAL) { 981 ret = krb5_ret_principal (sp, &creds->server); 982 if(ret) goto cleanup; 983 } 984 if (header & SC_SESSION_KEY) { 985 ret = krb5_ret_keyblock (sp, &creds->session); 986 if(ret) goto cleanup; 987 } 988 ret = krb5_ret_times (sp, &creds->times); 989 if(ret) goto cleanup; 990 ret = krb5_ret_int8 (sp, &dummy8); 991 if(ret) goto cleanup; 992 ret = krb5_ret_int32 (sp, &dummy32); 993 if(ret) goto cleanup; 994 /* 995 * Runtime detect the what is the higher bits of the bitfield. If 996 * any of the higher bits are set in the input data, it's either a 997 * new ticket flag (and this code need to be removed), or it's a 998 * MIT cache (or new Heimdal cache), lets change it to our current 999 * format. 1000 */ 1001 { 1002 uint32_t mask = 0xffff0000; 1003 creds->flags.i = 0; 1004 creds->flags.b.anonymous = 1; 1005 if (creds->flags.i & mask) 1006 mask = ~mask; 1007 if (dummy32 & mask) 1008 dummy32 = bitswap32(dummy32); 1009 } 1010 creds->flags.i = dummy32; 1011 if (header & SC_ADDRESSES) { 1012 ret = krb5_ret_addrs (sp, &creds->addresses); 1013 if(ret) goto cleanup; 1014 } 1015 if (header & SC_AUTHDATA) { 1016 ret = krb5_ret_authdata (sp, &creds->authdata); 1017 if(ret) goto cleanup; 1018 } 1019 if (header & SC_TICKET) { 1020 ret = krb5_ret_data (sp, &creds->ticket); 1021 if(ret) goto cleanup; 1022 } 1023 if (header & SC_SECOND_TICKET) { 1024 ret = krb5_ret_data (sp, &creds->second_ticket); 1025 if(ret) goto cleanup; 1026 } 1027 1028cleanup: 1029 if(ret) { 1030#if 0 1031 krb5_free_cred_contents(context, creds); /* XXX */ 1032#endif 1033 } 1034 return ret; 1035} 1036