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