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 36 #define KRB5_KT_VNO_1 1 37 #define KRB5_KT_VNO_2 2 38 #define KRB5_KT_VNO KRB5_KT_VNO_2 39 40 #define KRB5_KT_FL_JAVA 1 41 42 43 /* file operations -------------------------------------------- */ 44 45 struct fkt_data { 46 char *filename; 47 int flags; 48 }; 49 50 static krb5_error_code 51 krb5_kt_ret_data(krb5_context context, 52 krb5_storage *sp, 53 krb5_data *data) 54 { 55 int ret; 56 int16_t size; 57 ret = krb5_ret_int16(sp, &size); 58 if(ret) 59 return ret; 60 data->length = size; 61 data->data = malloc(size); 62 if (data->data == NULL) { 63 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 64 return ENOMEM; 65 } 66 ret = krb5_storage_read(sp, data->data, size); 67 if(ret != size) 68 return (ret < 0)? errno : KRB5_KT_END; 69 return 0; 70 } 71 72 static krb5_error_code 73 krb5_kt_ret_string(krb5_context context, 74 krb5_storage *sp, 75 heim_general_string *data) 76 { 77 int ret; 78 int16_t size; 79 ret = krb5_ret_int16(sp, &size); 80 if(ret) 81 return ret; 82 *data = malloc(size + 1); 83 if (*data == NULL) { 84 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 85 return ENOMEM; 86 } 87 ret = krb5_storage_read(sp, *data, size); 88 (*data)[size] = '\0'; 89 if(ret != size) 90 return (ret < 0)? errno : KRB5_KT_END; 91 return 0; 92 } 93 94 static krb5_error_code 95 krb5_kt_store_data(krb5_context context, 96 krb5_storage *sp, 97 krb5_data data) 98 { 99 int ret; 100 ret = krb5_store_int16(sp, data.length); 101 if(ret < 0) 102 return ret; 103 ret = krb5_storage_write(sp, data.data, data.length); 104 if(ret != (int)data.length){ 105 if(ret < 0) 106 return errno; 107 return KRB5_KT_END; 108 } 109 return 0; 110 } 111 112 static krb5_error_code 113 krb5_kt_store_string(krb5_storage *sp, 114 heim_general_string data) 115 { 116 int ret; 117 size_t len = strlen(data); 118 ret = krb5_store_int16(sp, len); 119 if(ret < 0) 120 return ret; 121 ret = krb5_storage_write(sp, data, len); 122 if(ret != (int)len){ 123 if(ret < 0) 124 return errno; 125 return KRB5_KT_END; 126 } 127 return 0; 128 } 129 130 static krb5_error_code 131 krb5_kt_ret_keyblock(krb5_context context, 132 struct fkt_data *fkt, 133 krb5_storage *sp, 134 krb5_keyblock *p) 135 { 136 int ret; 137 int16_t tmp; 138 139 ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */ 140 if(ret) { 141 krb5_set_error_message(context, ret, 142 N_("Cant read keyblock from file %s", ""), 143 fkt->filename); 144 return ret; 145 } 146 p->keytype = tmp; 147 ret = krb5_kt_ret_data(context, sp, &p->keyvalue); 148 if (ret) 149 krb5_set_error_message(context, ret, 150 N_("Cant read keyblock from file %s", ""), 151 fkt->filename); 152 return ret; 153 } 154 155 static krb5_error_code 156 krb5_kt_store_keyblock(krb5_context context, 157 struct fkt_data *fkt, 158 krb5_storage *sp, 159 krb5_keyblock *p) 160 { 161 int ret; 162 163 ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */ 164 if(ret) { 165 krb5_set_error_message(context, ret, 166 N_("Cant store keyblock to file %s", ""), 167 fkt->filename); 168 return ret; 169 } 170 ret = krb5_kt_store_data(context, sp, p->keyvalue); 171 if (ret) 172 krb5_set_error_message(context, ret, 173 N_("Cant store keyblock to file %s", ""), 174 fkt->filename); 175 return ret; 176 } 177 178 179 static krb5_error_code 180 krb5_kt_ret_principal(krb5_context context, 181 struct fkt_data *fkt, 182 krb5_storage *sp, 183 krb5_principal *princ) 184 { 185 size_t i; 186 int ret; 187 krb5_principal p; 188 int16_t len; 189 190 ALLOC(p, 1); 191 if(p == NULL) { 192 krb5_set_error_message(context, ENOMEM, 193 N_("malloc: out of memory", "")); 194 return ENOMEM; 195 } 196 197 ret = krb5_ret_int16(sp, &len); 198 if(ret) { 199 krb5_set_error_message(context, ret, 200 N_("Failed decoding length of " 201 "keytab principal in keytab file %s", ""), 202 fkt->filename); 203 goto out; 204 } 205 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 206 len--; 207 if (len < 0) { 208 ret = KRB5_KT_END; 209 krb5_set_error_message(context, ret, 210 N_("Keytab principal contains " 211 "invalid length in keytab %s", ""), 212 fkt->filename); 213 goto out; 214 } 215 ret = krb5_kt_ret_string(context, sp, &p->realm); 216 if(ret) { 217 krb5_set_error_message(context, ret, 218 N_("Can't read realm from keytab: %s", ""), 219 fkt->filename); 220 goto out; 221 } 222 p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val)); 223 if(p->name.name_string.val == NULL) { 224 ret = ENOMEM; 225 krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 226 goto out; 227 } 228 p->name.name_string.len = len; 229 for(i = 0; i < p->name.name_string.len; i++){ 230 ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i); 231 if(ret) { 232 krb5_set_error_message(context, ret, 233 N_("Can't read principal from " 234 "keytab: %s", ""), 235 fkt->filename); 236 goto out; 237 } 238 } 239 if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) 240 p->name.name_type = KRB5_NT_UNKNOWN; 241 else { 242 int32_t tmp32; 243 ret = krb5_ret_int32(sp, &tmp32); 244 p->name.name_type = tmp32; 245 if (ret) { 246 krb5_set_error_message(context, ret, 247 N_("Can't read name-type from " 248 "keytab: %s", ""), 249 fkt->filename); 250 goto out; 251 } 252 } 253 *princ = p; 254 return 0; 255 out: 256 krb5_free_principal(context, p); 257 return ret; 258 } 259 260 static krb5_error_code 261 krb5_kt_store_principal(krb5_context context, 262 krb5_storage *sp, 263 krb5_principal p) 264 { 265 size_t i; 266 int ret; 267 268 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 269 ret = krb5_store_int16(sp, p->name.name_string.len + 1); 270 else 271 ret = krb5_store_int16(sp, p->name.name_string.len); 272 if(ret) return ret; 273 ret = krb5_kt_store_string(sp, p->realm); 274 if(ret) return ret; 275 for(i = 0; i < p->name.name_string.len; i++){ 276 ret = krb5_kt_store_string(sp, p->name.name_string.val[i]); 277 if(ret) 278 return ret; 279 } 280 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { 281 ret = krb5_store_int32(sp, p->name.name_type); 282 if(ret) 283 return ret; 284 } 285 286 return 0; 287 } 288 289 static krb5_error_code KRB5_CALLCONV 290 fkt_resolve(krb5_context context, const char *name, krb5_keytab id) 291 { 292 struct fkt_data *d; 293 294 d = malloc(sizeof(*d)); 295 if(d == NULL) { 296 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 297 return ENOMEM; 298 } 299 d->filename = strdup(name); 300 if(d->filename == NULL) { 301 free(d); 302 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 303 return ENOMEM; 304 } 305 d->flags = 0; 306 id->data = d; 307 return 0; 308 } 309 310 static krb5_error_code KRB5_CALLCONV 311 fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id) 312 { 313 krb5_error_code ret; 314 315 ret = fkt_resolve(context, name, id); 316 if (ret == 0) { 317 struct fkt_data *d = id->data; 318 d->flags |= KRB5_KT_FL_JAVA; 319 } 320 return ret; 321 } 322 323 static krb5_error_code KRB5_CALLCONV 324 fkt_close(krb5_context context, krb5_keytab id) 325 { 326 struct fkt_data *d = id->data; 327 free(d->filename); 328 free(d); 329 return 0; 330 } 331 332 static krb5_error_code KRB5_CALLCONV 333 fkt_destroy(krb5_context context, krb5_keytab id) 334 { 335 struct fkt_data *d = id->data; 336 _krb5_erase_file(context, d->filename); 337 return 0; 338 } 339 340 static krb5_error_code KRB5_CALLCONV 341 fkt_get_name(krb5_context context, 342 krb5_keytab id, 343 char *name, 344 size_t namesize) 345 { 346 /* This function is XXX */ 347 struct fkt_data *d = id->data; 348 strlcpy(name, d->filename, namesize); 349 return 0; 350 } 351 352 static void 353 storage_set_flags(krb5_context context, krb5_storage *sp, int vno) 354 { 355 int flags = 0; 356 switch(vno) { 357 case KRB5_KT_VNO_1: 358 flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS; 359 flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE; 360 flags |= KRB5_STORAGE_HOST_BYTEORDER; 361 break; 362 case KRB5_KT_VNO_2: 363 break; 364 default: 365 krb5_warnx(context, 366 "storage_set_flags called with bad vno (%d)", vno); 367 } 368 krb5_storage_set_flags(sp, flags); 369 } 370 371 static krb5_error_code 372 fkt_start_seq_get_int(krb5_context context, 373 krb5_keytab id, 374 int flags, 375 int exclusive, 376 krb5_kt_cursor *c) 377 { 378 int8_t pvno, tag; 379 krb5_error_code ret; 380 struct fkt_data *d = id->data; 381 382 c->fd = open (d->filename, flags); 383 if (c->fd < 0) { 384 ret = errno; 385 krb5_set_error_message(context, ret, 386 N_("keytab %s open failed: %s", ""), 387 d->filename, strerror(ret)); 388 return ret; 389 } 390 rk_cloexec(c->fd); 391 ret = _krb5_xlock(context, c->fd, exclusive, d->filename); 392 if (ret) { 393 close(c->fd); 394 return ret; 395 } 396 c->sp = krb5_storage_from_fd(c->fd); 397 if (c->sp == NULL) { 398 _krb5_xunlock(context, c->fd); 399 close(c->fd); 400 krb5_set_error_message(context, ENOMEM, 401 N_("malloc: out of memory", "")); 402 return ENOMEM; 403 } 404 krb5_storage_set_eof_code(c->sp, KRB5_KT_END); 405 ret = krb5_ret_int8(c->sp, &pvno); 406 if(ret) { 407 krb5_storage_free(c->sp); 408 _krb5_xunlock(context, c->fd); 409 close(c->fd); 410 krb5_clear_error_message(context); 411 return ret; 412 } 413 if(pvno != 5) { 414 krb5_storage_free(c->sp); 415 _krb5_xunlock(context, c->fd); 416 close(c->fd); 417 krb5_clear_error_message (context); 418 return KRB5_KEYTAB_BADVNO; 419 } 420 ret = krb5_ret_int8(c->sp, &tag); 421 if (ret) { 422 krb5_storage_free(c->sp); 423 _krb5_xunlock(context, c->fd); 424 close(c->fd); 425 krb5_clear_error_message(context); 426 return ret; 427 } 428 id->version = tag; 429 storage_set_flags(context, c->sp, id->version); 430 return 0; 431 } 432 433 static krb5_error_code KRB5_CALLCONV 434 fkt_start_seq_get(krb5_context context, 435 krb5_keytab id, 436 krb5_kt_cursor *c) 437 { 438 return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY | O_CLOEXEC, 0, c); 439 } 440 441 static krb5_error_code 442 fkt_next_entry_int(krb5_context context, 443 krb5_keytab id, 444 krb5_keytab_entry *entry, 445 krb5_kt_cursor *cursor, 446 off_t *start, 447 off_t *end) 448 { 449 struct fkt_data *d = id->data; 450 int32_t len; 451 int ret; 452 int8_t tmp8; 453 int32_t tmp32; 454 uint32_t utmp32; 455 off_t pos, curpos; 456 457 pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); 458 loop: 459 ret = krb5_ret_int32(cursor->sp, &len); 460 if (ret) 461 return ret; 462 if(len < 0) { 463 pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR); 464 goto loop; 465 } 466 ret = krb5_kt_ret_principal (context, d, cursor->sp, &entry->principal); 467 if (ret) 468 goto out; 469 ret = krb5_ret_uint32(cursor->sp, &utmp32); 470 entry->timestamp = utmp32; 471 if (ret) 472 goto out; 473 ret = krb5_ret_int8(cursor->sp, &tmp8); 474 if (ret) 475 goto out; 476 entry->vno = tmp8; 477 ret = krb5_kt_ret_keyblock (context, d, cursor->sp, &entry->keyblock); 478 if (ret) 479 goto out; 480 /* there might be a 32 bit kvno here 481 * if it's zero, assume that the 8bit one was right, 482 * otherwise trust the new value */ 483 curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); 484 if(len + 4 + pos - curpos >= 4) { 485 ret = krb5_ret_int32(cursor->sp, &tmp32); 486 if (ret == 0 && tmp32 != 0) 487 entry->vno = tmp32; 488 } 489 /* there might be a flags field here */ 490 if(len + 4 + pos - curpos >= 8) { 491 ret = krb5_ret_uint32(cursor->sp, &utmp32); 492 if (ret == 0) 493 entry->flags = utmp32; 494 } else 495 entry->flags = 0; 496 497 entry->aliases = NULL; 498 499 if(start) *start = pos; 500 if(end) *end = pos + 4 + len; 501 out: 502 krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); 503 return ret; 504 } 505 506 static krb5_error_code KRB5_CALLCONV 507 fkt_next_entry(krb5_context context, 508 krb5_keytab id, 509 krb5_keytab_entry *entry, 510 krb5_kt_cursor *cursor) 511 { 512 return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL); 513 } 514 515 static krb5_error_code KRB5_CALLCONV 516 fkt_end_seq_get(krb5_context context, 517 krb5_keytab id, 518 krb5_kt_cursor *cursor) 519 { 520 krb5_storage_free(cursor->sp); 521 _krb5_xunlock(context, cursor->fd); 522 close(cursor->fd); 523 return 0; 524 } 525 526 static krb5_error_code KRB5_CALLCONV 527 fkt_setup_keytab(krb5_context context, 528 krb5_keytab id, 529 krb5_storage *sp) 530 { 531 krb5_error_code ret; 532 ret = krb5_store_int8(sp, 5); 533 if(ret) 534 return ret; 535 if(id->version == 0) 536 id->version = KRB5_KT_VNO; 537 return krb5_store_int8 (sp, id->version); 538 } 539 540 static krb5_error_code KRB5_CALLCONV 541 fkt_add_entry(krb5_context context, 542 krb5_keytab id, 543 krb5_keytab_entry *entry) 544 { 545 int ret; 546 int fd; 547 krb5_storage *sp; 548 struct fkt_data *d = id->data; 549 krb5_data keytab; 550 int32_t len; 551 552 fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC); 553 if (fd < 0) { 554 fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); 555 if (fd < 0) { 556 ret = errno; 557 krb5_set_error_message(context, ret, 558 N_("open(%s): %s", ""), d->filename, 559 strerror(ret)); 560 return ret; 561 } 562 rk_cloexec(fd); 563 564 ret = _krb5_xlock(context, fd, 1, d->filename); 565 if (ret) { 566 close(fd); 567 return ret; 568 } 569 sp = krb5_storage_from_fd(fd); 570 krb5_storage_set_eof_code(sp, KRB5_KT_END); 571 ret = fkt_setup_keytab(context, id, sp); 572 if(ret) { 573 goto out; 574 } 575 storage_set_flags(context, sp, id->version); 576 } else { 577 int8_t pvno, tag; 578 579 rk_cloexec(fd); 580 581 ret = _krb5_xlock(context, fd, 1, d->filename); 582 if (ret) { 583 close(fd); 584 return ret; 585 } 586 sp = krb5_storage_from_fd(fd); 587 krb5_storage_set_eof_code(sp, KRB5_KT_END); 588 ret = krb5_ret_int8(sp, &pvno); 589 if(ret) { 590 /* we probably have a zero byte file, so try to set it up 591 properly */ 592 ret = fkt_setup_keytab(context, id, sp); 593 if(ret) { 594 krb5_set_error_message(context, ret, 595 N_("%s: keytab is corrupted: %s", ""), 596 d->filename, strerror(ret)); 597 goto out; 598 } 599 storage_set_flags(context, sp, id->version); 600 } else { 601 if(pvno != 5) { 602 ret = KRB5_KEYTAB_BADVNO; 603 krb5_set_error_message(context, ret, 604 N_("Bad version in keytab %s", ""), 605 d->filename); 606 goto out; 607 } 608 ret = krb5_ret_int8 (sp, &tag); 609 if (ret) { 610 krb5_set_error_message(context, ret, 611 N_("failed reading tag from " 612 "keytab %s", ""), 613 d->filename); 614 goto out; 615 } 616 id->version = tag; 617 storage_set_flags(context, sp, id->version); 618 } 619 } 620 621 { 622 krb5_storage *emem; 623 emem = krb5_storage_emem(); 624 if(emem == NULL) { 625 ret = ENOMEM; 626 krb5_set_error_message(context, ret, 627 N_("malloc: out of memory", "")); 628 goto out; 629 } 630 ret = krb5_kt_store_principal(context, emem, entry->principal); 631 if(ret) { 632 krb5_set_error_message(context, ret, 633 N_("Failed storing principal " 634 "in keytab %s", ""), 635 d->filename); 636 krb5_storage_free(emem); 637 goto out; 638 } 639 ret = krb5_store_int32 (emem, entry->timestamp); 640 if(ret) { 641 krb5_set_error_message(context, ret, 642 N_("Failed storing timpstamp " 643 "in keytab %s", ""), 644 d->filename); 645 krb5_storage_free(emem); 646 goto out; 647 } 648 ret = krb5_store_int8 (emem, entry->vno % 256); 649 if(ret) { 650 krb5_set_error_message(context, ret, 651 N_("Failed storing kvno " 652 "in keytab %s", ""), 653 d->filename); 654 krb5_storage_free(emem); 655 goto out; 656 } 657 ret = krb5_kt_store_keyblock (context, d, emem, &entry->keyblock); 658 if(ret) { 659 krb5_storage_free(emem); 660 goto out; 661 } 662 if ((d->flags & KRB5_KT_FL_JAVA) == 0) { 663 ret = krb5_store_int32 (emem, entry->vno); 664 if (ret) { 665 krb5_set_error_message(context, ret, 666 N_("Failed storing extended kvno " 667 "in keytab %s", ""), 668 d->filename); 669 krb5_storage_free(emem); 670 goto out; 671 } 672 ret = krb5_store_uint32 (emem, entry->flags); 673 if (ret) { 674 krb5_set_error_message(context, ret, 675 N_("Failed storing extended kvno " 676 "in keytab %s", ""), 677 d->filename); 678 krb5_storage_free(emem); 679 goto out; 680 } 681 } 682 683 ret = krb5_storage_to_data(emem, &keytab); 684 krb5_storage_free(emem); 685 if(ret) { 686 krb5_set_error_message(context, ret, 687 N_("Failed converting keytab entry " 688 "to memory block for keytab %s", ""), 689 d->filename); 690 goto out; 691 } 692 } 693 694 while(1) { 695 ret = krb5_ret_int32(sp, &len); 696 if(ret == KRB5_KT_END) { 697 len = keytab.length; 698 break; 699 } 700 if(len < 0) { 701 len = -len; 702 if(len >= (int)keytab.length) { 703 krb5_storage_seek(sp, -4, SEEK_CUR); 704 break; 705 } 706 } 707 krb5_storage_seek(sp, len, SEEK_CUR); 708 } 709 ret = krb5_store_int32(sp, len); 710 if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) { 711 ret = errno; 712 krb5_set_error_message(context, ret, 713 N_("Failed writing keytab block " 714 "in keytab %s: %s", ""), 715 d->filename, strerror(ret)); 716 } 717 memset(keytab.data, 0, keytab.length); 718 krb5_data_free(&keytab); 719 out: 720 krb5_storage_free(sp); 721 _krb5_xunlock(context, fd); 722 close(fd); 723 return ret; 724 } 725 726 static krb5_error_code KRB5_CALLCONV 727 fkt_remove_entry(krb5_context context, 728 krb5_keytab id, 729 krb5_keytab_entry *entry) 730 { 731 krb5_keytab_entry e; 732 krb5_kt_cursor cursor; 733 off_t pos_start, pos_end; 734 int found = 0; 735 krb5_error_code ret; 736 737 ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY | O_CLOEXEC, 1, &cursor); 738 if(ret != 0) 739 goto out; /* return other error here? */ 740 while(fkt_next_entry_int(context, id, &e, &cursor, 741 &pos_start, &pos_end) == 0) { 742 if(krb5_kt_compare(context, &e, entry->principal, 743 entry->vno, entry->keyblock.keytype)) { 744 int32_t len; 745 unsigned char buf[128]; 746 found = 1; 747 krb5_storage_seek(cursor.sp, pos_start, SEEK_SET); 748 len = pos_end - pos_start - 4; 749 krb5_store_int32(cursor.sp, -len); 750 memset(buf, 0, sizeof(buf)); 751 while(len > 0) { 752 krb5_storage_write(cursor.sp, buf, 753 min((size_t)len, sizeof(buf))); 754 len -= min((size_t)len, sizeof(buf)); 755 } 756 } 757 krb5_kt_free_entry(context, &e); 758 } 759 krb5_kt_end_seq_get(context, id, &cursor); 760 out: 761 if (!found) { 762 krb5_clear_error_message (context); 763 return KRB5_KT_NOTFOUND; 764 } 765 return 0; 766 } 767 768 const krb5_kt_ops krb5_fkt_ops = { 769 "FILE", 770 fkt_resolve, 771 fkt_get_name, 772 fkt_close, 773 fkt_destroy, 774 NULL, /* get */ 775 fkt_start_seq_get, 776 fkt_next_entry, 777 fkt_end_seq_get, 778 fkt_add_entry, 779 fkt_remove_entry 780 }; 781 782 const krb5_kt_ops krb5_wrfkt_ops = { 783 "WRFILE", 784 fkt_resolve, 785 fkt_get_name, 786 fkt_close, 787 fkt_destroy, 788 NULL, /* get */ 789 fkt_start_seq_get, 790 fkt_next_entry, 791 fkt_end_seq_get, 792 fkt_add_entry, 793 fkt_remove_entry 794 }; 795 796 const krb5_kt_ops krb5_javakt_ops = { 797 "JAVA14", 798 fkt_resolve_java14, 799 fkt_get_name, 800 fkt_close, 801 fkt_destroy, 802 NULL, /* get */ 803 fkt_start_seq_get, 804 fkt_next_entry, 805 fkt_end_seq_get, 806 fkt_add_entry, 807 fkt_remove_entry 808 }; 809