1 /* 2 * Copyright (c) 1997 - 2003 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 "kadm5_locl.h" 35 36 RCSID("$Id: log.c,v 1.20 2003/04/16 17:56:55 lha Exp $"); 37 38 /* 39 * A log record consists of: 40 * 41 * version number 4 bytes 42 * time in seconds 4 bytes 43 * operation (enum kadm_ops) 4 bytes 44 * length of record 4 bytes 45 * data... n bytes 46 * length of record 4 bytes 47 * version number 4 bytes 48 * 49 */ 50 51 kadm5_ret_t 52 kadm5_log_get_version_fd (int fd, 53 u_int32_t *ver) 54 { 55 int ret; 56 krb5_storage *sp; 57 int32_t old_version; 58 59 ret = lseek (fd, 0, SEEK_END); 60 if(ret < 0) 61 return errno; 62 if(ret == 0) { 63 *ver = 0; 64 return 0; 65 } 66 sp = krb5_storage_from_fd (fd); 67 krb5_storage_seek(sp, -4, SEEK_CUR); 68 krb5_ret_int32 (sp, &old_version); 69 *ver = old_version; 70 krb5_storage_free(sp); 71 lseek (fd, 0, SEEK_END); 72 return 0; 73 } 74 75 kadm5_ret_t 76 kadm5_log_get_version (kadm5_server_context *context, u_int32_t *ver) 77 { 78 return kadm5_log_get_version_fd (context->log_context.log_fd, ver); 79 } 80 81 kadm5_ret_t 82 kadm5_log_set_version (kadm5_server_context *context, u_int32_t vno) 83 { 84 kadm5_log_context *log_context = &context->log_context; 85 86 log_context->version = vno; 87 return 0; 88 } 89 90 kadm5_ret_t 91 kadm5_log_init (kadm5_server_context *context) 92 { 93 int fd; 94 kadm5_ret_t ret; 95 kadm5_log_context *log_context = &context->log_context; 96 97 if (log_context->log_fd != -1) 98 return 0; 99 fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600); 100 if (fd < 0) 101 return errno; 102 if (flock (fd, LOCK_EX) < 0) { 103 close (fd); 104 return errno; 105 } 106 107 ret = kadm5_log_get_version_fd (fd, &log_context->version); 108 if (ret) 109 return ret; 110 111 log_context->log_fd = fd; 112 return 0; 113 } 114 115 kadm5_ret_t 116 kadm5_log_reinit (kadm5_server_context *context) 117 { 118 int fd; 119 kadm5_log_context *log_context = &context->log_context; 120 121 if (log_context->log_fd != -1) { 122 close (log_context->log_fd); 123 log_context->log_fd = -1; 124 } 125 fd = open (log_context->log_file, O_RDWR | O_CREAT | O_TRUNC, 0600); 126 if (fd < 0) 127 return errno; 128 if (flock (fd, LOCK_EX) < 0) { 129 close (fd); 130 return errno; 131 } 132 133 log_context->version = 0; 134 log_context->log_fd = fd; 135 return 0; 136 } 137 138 139 kadm5_ret_t 140 kadm5_log_end (kadm5_server_context *context) 141 { 142 kadm5_log_context *log_context = &context->log_context; 143 int fd = log_context->log_fd; 144 145 flock (fd, LOCK_UN); 146 close(fd); 147 log_context->log_fd = -1; 148 return 0; 149 } 150 151 static kadm5_ret_t 152 kadm5_log_preamble (kadm5_server_context *context, 153 krb5_storage *sp, 154 enum kadm_ops op) 155 { 156 kadm5_log_context *log_context = &context->log_context; 157 kadm5_ret_t kadm_ret; 158 159 kadm_ret = kadm5_log_init (context); 160 if (kadm_ret) 161 return kadm_ret; 162 163 krb5_store_int32 (sp, ++log_context->version); 164 krb5_store_int32 (sp, time(NULL)); 165 krb5_store_int32 (sp, op); 166 return 0; 167 } 168 169 static kadm5_ret_t 170 kadm5_log_postamble (kadm5_log_context *context, 171 krb5_storage *sp) 172 { 173 krb5_store_int32 (sp, context->version); 174 return 0; 175 } 176 177 /* 178 * flush the log record in `sp'. 179 */ 180 181 static kadm5_ret_t 182 kadm5_log_flush (kadm5_log_context *log_context, 183 krb5_storage *sp) 184 { 185 krb5_data data; 186 size_t len; 187 int ret; 188 189 krb5_storage_to_data(sp, &data); 190 len = data.length; 191 ret = write (log_context->log_fd, data.data, len); 192 if (ret != len) { 193 krb5_data_free(&data); 194 return errno; 195 } 196 if (fsync (log_context->log_fd) < 0) { 197 krb5_data_free(&data); 198 return errno; 199 } 200 /* 201 * Try to send a signal to any running `ipropd-master' 202 */ 203 sendto (log_context->socket_fd, 204 (void *)&log_context->version, 205 sizeof(log_context->version), 206 0, 207 (struct sockaddr *)&log_context->socket_name, 208 sizeof(log_context->socket_name)); 209 210 krb5_data_free(&data); 211 return 0; 212 } 213 214 /* 215 * Add a `create' operation to the log. 216 */ 217 218 kadm5_ret_t 219 kadm5_log_create (kadm5_server_context *context, 220 hdb_entry *ent) 221 { 222 krb5_storage *sp; 223 kadm5_ret_t ret; 224 krb5_data value; 225 kadm5_log_context *log_context = &context->log_context; 226 227 sp = krb5_storage_emem(); 228 ret = hdb_entry2value (context->context, ent, &value); 229 if (ret) { 230 krb5_storage_free(sp); 231 return ret; 232 } 233 ret = kadm5_log_preamble (context, sp, kadm_create); 234 if (ret) { 235 krb5_data_free (&value); 236 krb5_storage_free(sp); 237 return ret; 238 } 239 krb5_store_int32 (sp, value.length); 240 krb5_storage_write(sp, value.data, value.length); 241 krb5_store_int32 (sp, value.length); 242 krb5_data_free (&value); 243 ret = kadm5_log_postamble (log_context, sp); 244 if (ret) { 245 krb5_storage_free (sp); 246 return ret; 247 } 248 ret = kadm5_log_flush (log_context, sp); 249 krb5_storage_free (sp); 250 if (ret) 251 return ret; 252 ret = kadm5_log_end (context); 253 return ret; 254 } 255 256 /* 257 * Read the data of a create log record from `sp' and change the 258 * database. 259 */ 260 261 kadm5_ret_t 262 kadm5_log_replay_create (kadm5_server_context *context, 263 u_int32_t ver, 264 u_int32_t len, 265 krb5_storage *sp) 266 { 267 krb5_error_code ret; 268 krb5_data data; 269 hdb_entry ent; 270 271 ret = krb5_data_alloc (&data, len); 272 if (ret) 273 return ret; 274 krb5_storage_read (sp, data.data, len); 275 ret = hdb_value2entry (context->context, &data, &ent); 276 krb5_data_free(&data); 277 if (ret) 278 return ret; 279 ret = context->db->store(context->context, context->db, 0, &ent); 280 hdb_free_entry (context->context, &ent); 281 return ret; 282 } 283 284 /* 285 * Add a `delete' operation to the log. 286 */ 287 288 kadm5_ret_t 289 kadm5_log_delete (kadm5_server_context *context, 290 krb5_principal princ) 291 { 292 krb5_storage *sp; 293 kadm5_ret_t ret; 294 off_t off; 295 off_t len; 296 kadm5_log_context *log_context = &context->log_context; 297 298 sp = krb5_storage_emem(); 299 ret = kadm5_log_preamble (context, sp, kadm_delete); 300 if (ret) { 301 krb5_storage_free(sp); 302 return ret; 303 } 304 krb5_store_int32 (sp, 0); 305 off = krb5_storage_seek (sp, 0, SEEK_CUR); 306 krb5_store_principal (sp, princ); 307 len = krb5_storage_seek (sp, 0, SEEK_CUR) - off; 308 krb5_storage_seek(sp, -(len + 4), SEEK_CUR); 309 krb5_store_int32 (sp, len); 310 krb5_storage_seek(sp, len, SEEK_CUR); 311 krb5_store_int32 (sp, len); 312 if (ret) { 313 krb5_storage_free (sp); 314 return ret; 315 } 316 ret = kadm5_log_postamble (log_context, sp); 317 if (ret) { 318 krb5_storage_free (sp); 319 return ret; 320 } 321 ret = kadm5_log_flush (log_context, sp); 322 krb5_storage_free (sp); 323 if (ret) 324 return ret; 325 ret = kadm5_log_end (context); 326 return ret; 327 } 328 329 /* 330 * Read a `delete' log operation from `sp' and apply it. 331 */ 332 333 kadm5_ret_t 334 kadm5_log_replay_delete (kadm5_server_context *context, 335 u_int32_t ver, 336 u_int32_t len, 337 krb5_storage *sp) 338 { 339 krb5_error_code ret; 340 hdb_entry ent; 341 342 krb5_ret_principal (sp, &ent.principal); 343 344 ret = context->db->remove(context->context, context->db, &ent); 345 krb5_free_principal (context->context, ent.principal); 346 return ret; 347 } 348 349 /* 350 * Add a `rename' operation to the log. 351 */ 352 353 kadm5_ret_t 354 kadm5_log_rename (kadm5_server_context *context, 355 krb5_principal source, 356 hdb_entry *ent) 357 { 358 krb5_storage *sp; 359 kadm5_ret_t ret; 360 off_t off; 361 off_t len; 362 krb5_data value; 363 kadm5_log_context *log_context = &context->log_context; 364 365 sp = krb5_storage_emem(); 366 ret = hdb_entry2value (context->context, ent, &value); 367 if (ret) { 368 krb5_storage_free(sp); 369 return ret; 370 } 371 ret = kadm5_log_preamble (context, sp, kadm_rename); 372 if (ret) { 373 krb5_storage_free(sp); 374 krb5_data_free (&value); 375 return ret; 376 } 377 krb5_store_int32 (sp, 0); 378 off = krb5_storage_seek (sp, 0, SEEK_CUR); 379 krb5_store_principal (sp, source); 380 krb5_storage_write(sp, value.data, value.length); 381 krb5_data_free (&value); 382 len = krb5_storage_seek (sp, 0, SEEK_CUR) - off; 383 384 krb5_storage_seek(sp, -(len + 4), SEEK_CUR); 385 krb5_store_int32 (sp, len); 386 krb5_storage_seek(sp, len, SEEK_CUR); 387 krb5_store_int32 (sp, len); 388 if (ret) { 389 krb5_storage_free (sp); 390 return ret; 391 } 392 ret = kadm5_log_postamble (log_context, sp); 393 if (ret) { 394 krb5_storage_free (sp); 395 return ret; 396 } 397 ret = kadm5_log_flush (log_context, sp); 398 krb5_storage_free (sp); 399 if (ret) 400 return ret; 401 ret = kadm5_log_end (context); 402 return ret; 403 } 404 405 /* 406 * Read a `rename' log operation from `sp' and apply it. 407 */ 408 409 kadm5_ret_t 410 kadm5_log_replay_rename (kadm5_server_context *context, 411 u_int32_t ver, 412 u_int32_t len, 413 krb5_storage *sp) 414 { 415 krb5_error_code ret; 416 krb5_principal source; 417 hdb_entry source_ent, target_ent; 418 krb5_data value; 419 off_t off; 420 size_t princ_len, data_len; 421 422 off = krb5_storage_seek(sp, 0, SEEK_CUR); 423 krb5_ret_principal (sp, &source); 424 princ_len = krb5_storage_seek(sp, 0, SEEK_CUR) - off; 425 data_len = len - princ_len; 426 ret = krb5_data_alloc (&value, data_len); 427 if (ret) { 428 krb5_free_principal (context->context, source); 429 return ret; 430 } 431 krb5_storage_read (sp, value.data, data_len); 432 ret = hdb_value2entry (context->context, &value, &target_ent); 433 krb5_data_free(&value); 434 if (ret) { 435 krb5_free_principal (context->context, source); 436 return ret; 437 } 438 ret = context->db->store (context->context, context->db, 0, &target_ent); 439 hdb_free_entry (context->context, &target_ent); 440 if (ret) { 441 krb5_free_principal (context->context, source); 442 return ret; 443 } 444 source_ent.principal = source; 445 ret = context->db->remove (context->context, context->db, &source_ent); 446 krb5_free_principal (context->context, source); 447 return ret; 448 } 449 450 451 /* 452 * Add a `modify' operation to the log. 453 */ 454 455 kadm5_ret_t 456 kadm5_log_modify (kadm5_server_context *context, 457 hdb_entry *ent, 458 u_int32_t mask) 459 { 460 krb5_storage *sp; 461 kadm5_ret_t ret; 462 krb5_data value; 463 u_int32_t len; 464 kadm5_log_context *log_context = &context->log_context; 465 466 sp = krb5_storage_emem(); 467 ret = hdb_entry2value (context->context, ent, &value); 468 if (ret) { 469 krb5_storage_free(sp); 470 return ret; 471 } 472 ret = kadm5_log_preamble (context, sp, kadm_modify); 473 if (ret) { 474 krb5_data_free (&value); 475 krb5_storage_free(sp); 476 return ret; 477 } 478 len = value.length + 4; 479 krb5_store_int32 (sp, len); 480 krb5_store_int32 (sp, mask); 481 krb5_storage_write (sp, value.data, value.length); 482 krb5_data_free (&value); 483 krb5_store_int32 (sp, len); 484 if (ret) { 485 krb5_storage_free (sp); 486 return ret; 487 } 488 ret = kadm5_log_postamble (log_context, sp); 489 if (ret) { 490 krb5_storage_free (sp); 491 return ret; 492 } 493 ret = kadm5_log_flush (log_context, sp); 494 krb5_storage_free (sp); 495 if (ret) 496 return ret; 497 ret = kadm5_log_end (context); 498 return ret; 499 } 500 501 /* 502 * Read a `modify' log operation from `sp' and apply it. 503 */ 504 505 kadm5_ret_t 506 kadm5_log_replay_modify (kadm5_server_context *context, 507 u_int32_t ver, 508 u_int32_t len, 509 krb5_storage *sp) 510 { 511 krb5_error_code ret; 512 int32_t mask; 513 krb5_data value; 514 hdb_entry ent, log_ent; 515 516 krb5_ret_int32 (sp, &mask); 517 len -= 4; 518 ret = krb5_data_alloc (&value, len); 519 if (ret) 520 return ret; 521 krb5_storage_read (sp, value.data, len); 522 ret = hdb_value2entry (context->context, &value, &log_ent); 523 krb5_data_free(&value); 524 if (ret) 525 return ret; 526 ent.principal = log_ent.principal; 527 log_ent.principal = NULL; 528 ret = context->db->fetch(context->context, context->db, 529 HDB_F_DECRYPT, &ent); 530 if (ret) 531 return ret; 532 if (mask & KADM5_PRINC_EXPIRE_TIME) { 533 if (log_ent.valid_end == NULL) { 534 ent.valid_end = NULL; 535 } else { 536 if (ent.valid_end == NULL) 537 ent.valid_end = malloc(sizeof(*ent.valid_end)); 538 *ent.valid_end = *log_ent.valid_end; 539 } 540 } 541 if (mask & KADM5_PW_EXPIRATION) { 542 if (log_ent.pw_end == NULL) { 543 ent.pw_end = NULL; 544 } else { 545 if (ent.pw_end == NULL) 546 ent.pw_end = malloc(sizeof(*ent.pw_end)); 547 *ent.pw_end = *log_ent.pw_end; 548 } 549 } 550 if (mask & KADM5_LAST_PWD_CHANGE) { 551 abort (); /* XXX */ 552 } 553 if (mask & KADM5_ATTRIBUTES) { 554 ent.flags = log_ent.flags; 555 } 556 if (mask & KADM5_MAX_LIFE) { 557 if (log_ent.max_life == NULL) { 558 ent.max_life = NULL; 559 } else { 560 if (ent.max_life == NULL) 561 ent.max_life = malloc (sizeof(*ent.max_life)); 562 *ent.max_life = *log_ent.max_life; 563 } 564 } 565 if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) { 566 if (ent.modified_by == NULL) { 567 ent.modified_by = malloc(sizeof(*ent.modified_by)); 568 } else 569 free_Event(ent.modified_by); 570 copy_Event(log_ent.modified_by, ent.modified_by); 571 } 572 if (mask & KADM5_KVNO) { 573 ent.kvno = log_ent.kvno; 574 } 575 if (mask & KADM5_MKVNO) { 576 abort (); /* XXX */ 577 } 578 if (mask & KADM5_AUX_ATTRIBUTES) { 579 abort (); /* XXX */ 580 } 581 if (mask & KADM5_POLICY) { 582 abort (); /* XXX */ 583 } 584 if (mask & KADM5_POLICY_CLR) { 585 abort (); /* XXX */ 586 } 587 if (mask & KADM5_MAX_RLIFE) { 588 if (log_ent.max_renew == NULL) { 589 ent.max_renew = NULL; 590 } else { 591 if (ent.max_renew == NULL) 592 ent.max_renew = malloc (sizeof(*ent.max_renew)); 593 *ent.max_renew = *log_ent.max_renew; 594 } 595 } 596 if (mask & KADM5_LAST_SUCCESS) { 597 abort (); /* XXX */ 598 } 599 if (mask & KADM5_LAST_FAILED) { 600 abort (); /* XXX */ 601 } 602 if (mask & KADM5_FAIL_AUTH_COUNT) { 603 abort (); /* XXX */ 604 } 605 if (mask & KADM5_KEY_DATA) { 606 size_t len; 607 int i; 608 609 for (i = 0; i < ent.keys.len; ++i) 610 free_Key(&ent.keys.val[i]); 611 free (ent.keys.val); 612 613 len = log_ent.keys.len; 614 615 ent.keys.len = len; 616 ent.keys.val = malloc(len * sizeof(*ent.keys.val)); 617 for (i = 0; i < ent.keys.len; ++i) 618 copy_Key(&log_ent.keys.val[i], 619 &ent.keys.val[i]); 620 } 621 ret = context->db->store(context->context, context->db, 622 HDB_F_REPLACE, &ent); 623 hdb_free_entry (context->context, &ent); 624 hdb_free_entry (context->context, &log_ent); 625 return ret; 626 } 627 628 /* 629 * Add a `nop' operation to the log. 630 */ 631 632 kadm5_ret_t 633 kadm5_log_nop (kadm5_server_context *context) 634 { 635 krb5_storage *sp; 636 kadm5_ret_t ret; 637 kadm5_log_context *log_context = &context->log_context; 638 639 sp = krb5_storage_emem(); 640 ret = kadm5_log_preamble (context, sp, kadm_nop); 641 if (ret) { 642 krb5_storage_free (sp); 643 return ret; 644 } 645 krb5_store_int32 (sp, 0); 646 krb5_store_int32 (sp, 0); 647 ret = kadm5_log_postamble (log_context, sp); 648 if (ret) { 649 krb5_storage_free (sp); 650 return ret; 651 } 652 ret = kadm5_log_flush (log_context, sp); 653 krb5_storage_free (sp); 654 if (ret) 655 return ret; 656 ret = kadm5_log_end (context); 657 return ret; 658 } 659 660 /* 661 * Read a `nop' log operation from `sp' and apply it. 662 */ 663 664 kadm5_ret_t 665 kadm5_log_replay_nop (kadm5_server_context *context, 666 u_int32_t ver, 667 u_int32_t len, 668 krb5_storage *sp) 669 { 670 return 0; 671 } 672 673 /* 674 * Call `func' for each log record in the log in `context' 675 */ 676 677 kadm5_ret_t 678 kadm5_log_foreach (kadm5_server_context *context, 679 void (*func)(kadm5_server_context *server_context, 680 u_int32_t ver, 681 time_t timestamp, 682 enum kadm_ops op, 683 u_int32_t len, 684 krb5_storage *sp)) 685 { 686 int fd = context->log_context.log_fd; 687 krb5_storage *sp; 688 689 lseek (fd, 0, SEEK_SET); 690 sp = krb5_storage_from_fd (fd); 691 for (;;) { 692 int32_t ver, timestamp, op, len; 693 694 if(krb5_ret_int32 (sp, &ver) != 0) 695 break; 696 krb5_ret_int32 (sp, ×tamp); 697 krb5_ret_int32 (sp, &op); 698 krb5_ret_int32 (sp, &len); 699 (*func)(context, ver, timestamp, op, len, sp); 700 krb5_storage_seek(sp, 8, SEEK_CUR); 701 } 702 return 0; 703 } 704 705 /* 706 * Go to end of log. 707 */ 708 709 krb5_storage * 710 kadm5_log_goto_end (int fd) 711 { 712 krb5_storage *sp; 713 714 sp = krb5_storage_from_fd (fd); 715 krb5_storage_seek(sp, 0, SEEK_END); 716 return sp; 717 } 718 719 /* 720 * Return previous log entry. 721 */ 722 723 kadm5_ret_t 724 kadm5_log_previous (krb5_storage *sp, 725 u_int32_t *ver, 726 time_t *timestamp, 727 enum kadm_ops *op, 728 u_int32_t *len) 729 { 730 off_t off; 731 int32_t tmp; 732 733 krb5_storage_seek(sp, -8, SEEK_CUR); 734 krb5_ret_int32 (sp, &tmp); 735 *len = tmp; 736 krb5_ret_int32 (sp, &tmp); 737 *ver = tmp; 738 off = 24 + *len; 739 krb5_storage_seek(sp, -off, SEEK_CUR); 740 krb5_ret_int32 (sp, &tmp); 741 assert(tmp == *ver); 742 krb5_ret_int32 (sp, &tmp); 743 *timestamp = tmp; 744 krb5_ret_int32 (sp, &tmp); 745 *op = tmp; 746 krb5_ret_int32 (sp, &tmp); 747 assert(tmp == *len); 748 return 0; 749 } 750 751 /* 752 * Replay a record from the log 753 */ 754 755 kadm5_ret_t 756 kadm5_log_replay (kadm5_server_context *context, 757 enum kadm_ops op, 758 u_int32_t ver, 759 u_int32_t len, 760 krb5_storage *sp) 761 { 762 switch (op) { 763 case kadm_create : 764 return kadm5_log_replay_create (context, ver, len, sp); 765 case kadm_delete : 766 return kadm5_log_replay_delete (context, ver, len, sp); 767 case kadm_rename : 768 return kadm5_log_replay_rename (context, ver, len, sp); 769 case kadm_modify : 770 return kadm5_log_replay_modify (context, ver, len, sp); 771 case kadm_nop : 772 return kadm5_log_replay_nop (context, ver, len, sp); 773 default : 774 return KADM5_FAILURE; 775 } 776 } 777 778 /* 779 * truncate the log - i.e. create an empty file with just (nop vno + 2) 780 */ 781 782 kadm5_ret_t 783 kadm5_log_truncate (kadm5_server_context *server_context) 784 { 785 kadm5_ret_t ret; 786 u_int32_t vno; 787 788 ret = kadm5_log_init (server_context); 789 if (ret) 790 return ret; 791 792 ret = kadm5_log_get_version (server_context, &vno); 793 if (ret) 794 return ret; 795 796 ret = kadm5_log_reinit (server_context); 797 if (ret) 798 return ret; 799 800 ret = kadm5_log_set_version (server_context, vno + 1); 801 if (ret) 802 return ret; 803 804 ret = kadm5_log_nop (server_context); 805 if (ret) 806 return ret; 807 808 ret = kadm5_log_end (server_context); 809 if (ret) 810 return ret; 811 return 0; 812 813 } 814