log.c revision 120945
1157016Sdes/* 2157016Sdes * Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan 3157016Sdes * (Royal Institute of Technology, Stockholm, Sweden). 4157016Sdes * All rights reserved. 5157016Sdes * 6157016Sdes * Redistribution and use in source and binary forms, with or without 7157016Sdes * modification, are permitted provided that the following conditions 8157016Sdes * are met: 9157016Sdes * 10157016Sdes * 1. Redistributions of source code must retain the above copyright 11157016Sdes * notice, this list of conditions and the following disclaimer. 12157016Sdes * 13157016Sdes * 2. Redistributions in binary form must reproduce the above copyright 14157016Sdes * notice, this list of conditions and the following disclaimer in the 15157016Sdes * documentation and/or other materials provided with the distribution. 16157016Sdes * 17157016Sdes * 3. Neither the name of the Institute nor the names of its contributors 18157016Sdes * may be used to endorse or promote products derived from this software 19162852Sdes * without specific prior written permission. 20162852Sdes * 21162852Sdes * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22162852Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23162852Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24162852Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25162852Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26162852Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27162852Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28162852Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29162852Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30162852Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31162852Sdes * SUCH DAMAGE. 32181111Sdes */ 33157016Sdes 34157016Sdes#include "kadm5_locl.h" 35295367Sdes 36162852SdesRCSID("$Id: log.c,v 1.20 2003/04/16 17:56:55 lha Exp $"); 37295367Sdes 38157016Sdes/* 39157016Sdes * A log record consists of: 40157016Sdes * 41157016Sdes * version number 4 bytes 42157016Sdes * time in seconds 4 bytes 43157016Sdes * operation (enum kadm_ops) 4 bytes 44157016Sdes * length of record 4 bytes 45162852Sdes * data... n bytes 46157016Sdes * length of record 4 bytes 47157016Sdes * version number 4 bytes 48157016Sdes * 49157016Sdes */ 50157016Sdes 51157016Sdeskadm5_ret_t 52157016Sdeskadm5_log_get_version_fd (int fd, 53157016Sdes u_int32_t *ver) 54157016Sdes{ 55157016Sdes int ret; 56157016Sdes krb5_storage *sp; 57157016Sdes int32_t old_version; 58157016Sdes 59157016Sdes ret = lseek (fd, 0, SEEK_END); 60157016Sdes if(ret < 0) 61157016Sdes return errno; 62157016Sdes if(ret == 0) { 63157016Sdes *ver = 0; 64157016Sdes return 0; 65157016Sdes } 66157016Sdes sp = krb5_storage_from_fd (fd); 67157016Sdes krb5_storage_seek(sp, -4, SEEK_CUR); 68157016Sdes krb5_ret_int32 (sp, &old_version); 69157016Sdes *ver = old_version; 70157016Sdes krb5_storage_free(sp); 71157016Sdes lseek (fd, 0, SEEK_END); 72157016Sdes return 0; 73157016Sdes} 74157016Sdes 75157016Sdeskadm5_ret_t 76157016Sdeskadm5_log_get_version (kadm5_server_context *context, u_int32_t *ver) 77157016Sdes{ 78157016Sdes return kadm5_log_get_version_fd (context->log_context.log_fd, ver); 79157016Sdes} 80157016Sdes 81157016Sdeskadm5_ret_t 82157016Sdeskadm5_log_set_version (kadm5_server_context *context, u_int32_t vno) 83157016Sdes{ 84157016Sdes kadm5_log_context *log_context = &context->log_context; 85157016Sdes 86157016Sdes log_context->version = vno; 87157016Sdes return 0; 88157016Sdes} 89157016Sdes 90157016Sdeskadm5_ret_t 91157016Sdeskadm5_log_init (kadm5_server_context *context) 92157016Sdes{ 93157016Sdes int fd; 94157016Sdes kadm5_ret_t ret; 95157016Sdes kadm5_log_context *log_context = &context->log_context; 96157016Sdes 97157016Sdes if (log_context->log_fd != -1) 98157016Sdes return 0; 99157016Sdes fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600); 100157016Sdes if (fd < 0) 101157016Sdes return errno; 102157016Sdes if (flock (fd, LOCK_EX) < 0) { 103157016Sdes close (fd); 104157016Sdes return errno; 105157016Sdes } 106157016Sdes 107157016Sdes ret = kadm5_log_get_version_fd (fd, &log_context->version); 108157016Sdes if (ret) 109157016Sdes return ret; 110157016Sdes 111157016Sdes log_context->log_fd = fd; 112157016Sdes return 0; 113162852Sdes} 114162852Sdes 115157016Sdeskadm5_ret_t 116162852Sdeskadm5_log_reinit (kadm5_server_context *context) 117157016Sdes{ 118157016Sdes int fd; 119157016Sdes kadm5_log_context *log_context = &context->log_context; 120157016Sdes 121157016Sdes if (log_context->log_fd != -1) { 122157016Sdes close (log_context->log_fd); 123157016Sdes log_context->log_fd = -1; 124157016Sdes } 125157016Sdes fd = open (log_context->log_file, O_RDWR | O_CREAT | O_TRUNC, 0600); 126157016Sdes if (fd < 0) 127157016Sdes return errno; 128157016Sdes if (flock (fd, LOCK_EX) < 0) { 129157016Sdes close (fd); 130157016Sdes return errno; 131157016Sdes } 132157016Sdes 133157016Sdes log_context->version = 0; 134157016Sdes log_context->log_fd = fd; 135157016Sdes return 0; 136157016Sdes} 137157016Sdes 138157016Sdes 139157016Sdeskadm5_ret_t 140157016Sdeskadm5_log_end (kadm5_server_context *context) 141157016Sdes{ 142157016Sdes kadm5_log_context *log_context = &context->log_context; 143157016Sdes int fd = log_context->log_fd; 144157016Sdes 145157016Sdes flock (fd, LOCK_UN); 146157016Sdes close(fd); 147157016Sdes log_context->log_fd = -1; 148157016Sdes return 0; 149157016Sdes} 150157016Sdes 151157016Sdesstatic kadm5_ret_t 152157016Sdeskadm5_log_preamble (kadm5_server_context *context, 153157016Sdes krb5_storage *sp, 154157016Sdes enum kadm_ops op) 155157016Sdes{ 156157016Sdes kadm5_log_context *log_context = &context->log_context; 157157016Sdes kadm5_ret_t kadm_ret; 158157016Sdes 159157016Sdes kadm_ret = kadm5_log_init (context); 160157016Sdes if (kadm_ret) 161157016Sdes return kadm_ret; 162157016Sdes 163157016Sdes krb5_store_int32 (sp, ++log_context->version); 164157016Sdes krb5_store_int32 (sp, time(NULL)); 165157016Sdes krb5_store_int32 (sp, op); 166157016Sdes return 0; 167157016Sdes} 168157016Sdes 169157016Sdesstatic kadm5_ret_t 170157016Sdeskadm5_log_postamble (kadm5_log_context *context, 171157016Sdes krb5_storage *sp) 172157016Sdes{ 173157016Sdes krb5_store_int32 (sp, context->version); 174157016Sdes return 0; 175157016Sdes} 176157016Sdes 177215116Sdes/* 178215116Sdes * flush the log record in `sp'. 179215116Sdes */ 180215116Sdes 181215116Sdesstatic kadm5_ret_t 182157016Sdeskadm5_log_flush (kadm5_log_context *log_context, 183157016Sdes krb5_storage *sp) 184157016Sdes{ 185157016Sdes krb5_data data; 186157016Sdes size_t len; 187157016Sdes int ret; 188157016Sdes 189157016Sdes krb5_storage_to_data(sp, &data); 190157016Sdes len = data.length; 191157016Sdes ret = write (log_context->log_fd, data.data, len); 192157016Sdes if (ret != len) { 193157016Sdes krb5_data_free(&data); 194157016Sdes return errno; 195157016Sdes } 196157016Sdes if (fsync (log_context->log_fd) < 0) { 197157016Sdes krb5_data_free(&data); 198157016Sdes return errno; 199157016Sdes } 200157016Sdes /* 201157016Sdes * Try to send a signal to any running `ipropd-master' 202157016Sdes */ 203157016Sdes sendto (log_context->socket_fd, 204157016Sdes (void *)&log_context->version, 205157016Sdes sizeof(log_context->version), 206157016Sdes 0, 207157016Sdes (struct sockaddr *)&log_context->socket_name, 208157016Sdes sizeof(log_context->socket_name)); 209157016Sdes 210157016Sdes krb5_data_free(&data); 211157016Sdes return 0; 212157016Sdes} 213157016Sdes 214295367Sdes/* 215157016Sdes * Add a `create' operation to the log. 216157016Sdes */ 217157016Sdes 218157016Sdeskadm5_ret_t 219157016Sdeskadm5_log_create (kadm5_server_context *context, 220157016Sdes hdb_entry *ent) 221157016Sdes{ 222157016Sdes krb5_storage *sp; 223157016Sdes kadm5_ret_t ret; 224157016Sdes krb5_data value; 225157016Sdes kadm5_log_context *log_context = &context->log_context; 226157016Sdes 227157016Sdes sp = krb5_storage_emem(); 228157016Sdes ret = hdb_entry2value (context->context, ent, &value); 229157016Sdes if (ret) { 230157016Sdes krb5_storage_free(sp); 231157016Sdes return ret; 232157016Sdes } 233157016Sdes ret = kadm5_log_preamble (context, sp, kadm_create); 234157016Sdes if (ret) { 235157016Sdes krb5_data_free (&value); 236157016Sdes krb5_storage_free(sp); 237157016Sdes return ret; 238157016Sdes } 239157016Sdes krb5_store_int32 (sp, value.length); 240157016Sdes krb5_storage_write(sp, value.data, value.length); 241157016Sdes krb5_store_int32 (sp, value.length); 242157016Sdes krb5_data_free (&value); 243157016Sdes ret = kadm5_log_postamble (log_context, sp); 244157016Sdes if (ret) { 245157016Sdes krb5_storage_free (sp); 246157016Sdes return ret; 247295367Sdes } 248295367Sdes ret = kadm5_log_flush (log_context, sp); 249157016Sdes krb5_storage_free (sp); 250157016Sdes if (ret) 251157016Sdes return ret; 252157016Sdes ret = kadm5_log_end (context); 253157016Sdes return ret; 254157016Sdes} 255157016Sdes 256157016Sdes/* 257295367Sdes * Read the data of a create log record from `sp' and change the 258295367Sdes * database. 259157016Sdes */ 260295367Sdes 261295367Sdeskadm5_ret_t 262295367Sdeskadm5_log_replay_create (kadm5_server_context *context, 263295367Sdes u_int32_t ver, 264295367Sdes u_int32_t len, 265157016Sdes krb5_storage *sp) 266157016Sdes{ 267157016Sdes krb5_error_code ret; 268157016Sdes krb5_data data; 269157016Sdes hdb_entry ent; 270157016Sdes 271157016Sdes ret = krb5_data_alloc (&data, len); 272157016Sdes if (ret) 273157016Sdes return ret; 274157016Sdes krb5_storage_read (sp, data.data, len); 275157016Sdes ret = hdb_value2entry (context->context, &data, &ent); 276157016Sdes krb5_data_free(&data); 277157016Sdes if (ret) 278157016Sdes return ret; 279157016Sdes ret = context->db->store(context->context, context->db, 0, &ent); 280157016Sdes hdb_free_entry (context->context, &ent); 281157016Sdes return ret; 282157016Sdes} 283 284/* 285 * Add a `delete' operation to the log. 286 */ 287 288kadm5_ret_t 289kadm5_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 333kadm5_ret_t 334kadm5_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 353kadm5_ret_t 354kadm5_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 409kadm5_ret_t 410kadm5_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 455kadm5_ret_t 456kadm5_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 505kadm5_ret_t 506kadm5_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 632kadm5_ret_t 633kadm5_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 664kadm5_ret_t 665kadm5_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 677kadm5_ret_t 678kadm5_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 709krb5_storage * 710kadm5_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 723kadm5_ret_t 724kadm5_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 755kadm5_ret_t 756kadm5_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 782kadm5_ret_t 783kadm5_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