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 37 RCSID("$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 45 void KRB5_LIB_FUNCTION 46 krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) 47 { 48 sp->flags |= flags; 49 } 50 51 void KRB5_LIB_FUNCTION 52 krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) 53 { 54 sp->flags &= ~flags; 55 } 56 57 krb5_boolean KRB5_LIB_FUNCTION 58 krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) 59 { 60 return (sp->flags & flags) == flags; 61 } 62 63 void KRB5_LIB_FUNCTION 64 krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder) 65 { 66 sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK; 67 sp->flags |= byteorder; 68 } 69 70 krb5_flags KRB5_LIB_FUNCTION 71 krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder) 72 { 73 return sp->flags & KRB5_STORAGE_BYTEORDER_MASK; 74 } 75 76 off_t KRB5_LIB_FUNCTION 77 krb5_storage_seek(krb5_storage *sp, off_t offset, int whence) 78 { 79 return (*sp->seek)(sp, offset, whence); 80 } 81 82 krb5_ssize_t KRB5_LIB_FUNCTION 83 krb5_storage_read(krb5_storage *sp, void *buf, size_t len) 84 { 85 return sp->fetch(sp, buf, len); 86 } 87 88 krb5_ssize_t KRB5_LIB_FUNCTION 89 krb5_storage_write(krb5_storage *sp, const void *buf, size_t len) 90 { 91 return sp->store(sp, buf, len); 92 } 93 94 void KRB5_LIB_FUNCTION 95 krb5_storage_set_eof_code(krb5_storage *sp, int code) 96 { 97 sp->eof_code = code; 98 } 99 100 krb5_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 112 krb5_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 124 krb5_error_code KRB5_LIB_FUNCTION 125 krb5_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 134 krb5_error_code KRB5_LIB_FUNCTION 135 krb5_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 156 static krb5_error_code 157 krb5_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 173 krb5_error_code KRB5_LIB_FUNCTION 174 krb5_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 184 krb5_error_code KRB5_LIB_FUNCTION 185 krb5_store_uint32(krb5_storage *sp, 186 uint32_t value) 187 { 188 return krb5_store_int32(sp, (int32_t)value); 189 } 190 191 static krb5_error_code 192 krb5_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 207 krb5_error_code KRB5_LIB_FUNCTION 208 krb5_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 221 krb5_error_code KRB5_LIB_FUNCTION 222 krb5_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 235 krb5_error_code KRB5_LIB_FUNCTION 236 krb5_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 246 krb5_error_code KRB5_LIB_FUNCTION 247 krb5_store_uint16(krb5_storage *sp, 248 uint16_t value) 249 { 250 return krb5_store_int16(sp, (int16_t)value); 251 } 252 253 krb5_error_code KRB5_LIB_FUNCTION 254 krb5_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 270 krb5_error_code KRB5_LIB_FUNCTION 271 krb5_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 284 krb5_error_code KRB5_LIB_FUNCTION 285 krb5_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 296 krb5_error_code KRB5_LIB_FUNCTION 297 krb5_store_uint8(krb5_storage *sp, 298 uint8_t value) 299 { 300 return krb5_store_int8(sp, (int8_t)value); 301 } 302 303 krb5_error_code KRB5_LIB_FUNCTION 304 krb5_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 315 krb5_error_code KRB5_LIB_FUNCTION 316 krb5_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 329 krb5_error_code KRB5_LIB_FUNCTION 330 krb5_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 346 krb5_error_code KRB5_LIB_FUNCTION 347 krb5_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 367 krb5_error_code KRB5_LIB_FUNCTION 368 krb5_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 376 krb5_error_code KRB5_LIB_FUNCTION 377 krb5_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 394 krb5_error_code KRB5_LIB_FUNCTION 395 krb5_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 410 krb5_error_code KRB5_LIB_FUNCTION 411 krb5_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 443 krb5_error_code KRB5_LIB_FUNCTION 444 krb5_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 468 krb5_error_code KRB5_LIB_FUNCTION 469 krb5_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 514 krb5_error_code KRB5_LIB_FUNCTION 515 krb5_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 540 krb5_error_code KRB5_LIB_FUNCTION 541 krb5_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 597 krb5_error_code KRB5_LIB_FUNCTION 598 krb5_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 615 krb5_error_code KRB5_LIB_FUNCTION 616 krb5_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 634 krb5_error_code KRB5_LIB_FUNCTION 635 krb5_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 648 krb5_error_code KRB5_LIB_FUNCTION 649 krb5_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 667 krb5_error_code KRB5_LIB_FUNCTION 668 krb5_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 677 krb5_error_code KRB5_LIB_FUNCTION 678 krb5_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 689 krb5_error_code KRB5_LIB_FUNCTION 690 krb5_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 703 krb5_error_code KRB5_LIB_FUNCTION 704 krb5_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 723 krb5_error_code KRB5_LIB_FUNCTION 724 krb5_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 739 krb5_error_code KRB5_LIB_FUNCTION 740 krb5_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 761 static int32_t 762 bitswap32(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 778 krb5_error_code KRB5_LIB_FUNCTION 779 krb5_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 819 krb5_error_code KRB5_LIB_FUNCTION 820 krb5_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); 863 cleanup: 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 884 krb5_error_code KRB5_LIB_FUNCTION 885 krb5_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 963 krb5_error_code KRB5_LIB_FUNCTION 964 krb5_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 1028 cleanup: 1029 if(ret) { 1030 #if 0 1031 krb5_free_cred_contents(context, creds); /* XXX */ 1032 #endif 1033 } 1034 return ret; 1035 } 1036