log.c revision 55682
162587Sitojun/* 278064Sume * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan 362587Sitojun * (Royal Institute of Technology, Stockholm, Sweden). 452904Sshin * All rights reserved. 552904Sshin * 652904Sshin * Redistribution and use in source and binary forms, with or without 753541Sshin * modification, are permitted provided that the following conditions 852904Sshin * are met: 952904Sshin * 1052904Sshin * 1. Redistributions of source code must retain the above copyright 1152904Sshin * notice, this list of conditions and the following disclaimer. 1252904Sshin * 1352904Sshin * 2. Redistributions in binary form must reproduce the above copyright 1452904Sshin * notice, this list of conditions and the following disclaimer in the 1552904Sshin * documentation and/or other materials provided with the distribution. 1652904Sshin * 1752904Sshin * 3. Neither the name of the Institute nor the names of its contributors 1852904Sshin * may be used to endorse or promote products derived from this software 1953541Sshin * without specific prior written permission. 2052904Sshin * 2152904Sshin * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2252904Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2352904Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2452904Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2552904Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2652904Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2752904Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2852904Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2952904Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3052904Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3152904Sshin * SUCH DAMAGE. 3252904Sshin */ 3352904Sshin 3452904Sshin#include "kadm5_locl.h" 3552904Sshin 3652904SshinRCSID("$Id: log.c,v 1.13 1999/12/04 19:50:35 assar Exp $"); 3752904Sshin 3852904Sshin/* 3952904Sshin * A log record consists of: 4052904Sshin * 4152904Sshin * version number 4 bytes 4252904Sshin * time in seconds 4 bytes 4352904Sshin * operation (enum kadm_ops) 4 bytes 4452904Sshin * length of record 4 bytes 4552904Sshin * data... n bytes 4652904Sshin * length of record 4 bytes 4752904Sshin * version number 4 bytes 4852904Sshin * 4952904Sshin */ 5052904Sshin 5152904Sshinkadm5_ret_t 5252904Sshinkadm5_log_get_version (int fd, 5352904Sshin u_int32_t *ver) 5452904Sshin{ 5552904Sshin int ret; 5652904Sshin krb5_storage *sp; 5752904Sshin int32_t old_version; 5852904Sshin 5952904Sshin ret = lseek (fd, 0, SEEK_END); 6052904Sshin if(ret < 0) 6152904Sshin return errno; 6252904Sshin if(ret == 0) { 6352904Sshin *ver = 0; 6452904Sshin return 0; 6552904Sshin } 6652904Sshin sp = krb5_storage_from_fd (fd); 6752904Sshin sp->seek(sp, -4, SEEK_CUR); 6862587Sitojun krb5_ret_int32 (sp, &old_version); 6978064Sume *ver = old_version; 7057120Sshin krb5_storage_free(sp); 7157120Sshin lseek (fd, 0, SEEK_END); 7262587Sitojun return 0; 7362587Sitojun} 7462587Sitojun 7552904Sshinkadm5_ret_t 7652904Sshinkadm5_log_init (kadm5_server_context *context) 7778064Sume{ 7878064Sume int fd; 7952904Sshin kadm5_ret_t ret; 8062587Sitojun kadm5_log_context *log_context = &context->log_context; 8178064Sume 8252904Sshin if (log_context->log_fd != -1) 8352904Sshin return 0; 8452904Sshin fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600); 8552904Sshin if (fd < 0) 8652904Sshin return errno; 8752904Sshin if (flock (fd, LOCK_EX) < 0) { 8852904Sshin close (fd); 8952904Sshin return errno; 9052904Sshin } 9152904Sshin 9262587Sitojun ret = kadm5_log_get_version (fd, &log_context->version); 9352904Sshin if (ret) 9452904Sshin return ret; 9552904Sshin 9652904Sshin log_context->log_fd = fd; 9752904Sshin return 0; 9852904Sshin} 9952904Sshin 10052904Sshinkadm5_ret_t 10152904Sshinkadm5_log_end (kadm5_server_context *context) 10252904Sshin{ 10352904Sshin kadm5_log_context *log_context = &context->log_context; 10452904Sshin int fd = log_context->log_fd; 10552904Sshin 10652904Sshin flock (fd, LOCK_UN); 10752904Sshin close(fd); 10852904Sshin log_context->log_fd = -1; 10952904Sshin return 0; 11097181Smike} 11152904Sshin 11252904Sshinstatic kadm5_ret_t 11352904Sshinkadm5_log_preamble (kadm5_server_context *context, 11452904Sshin krb5_storage *sp, 11552904Sshin enum kadm_ops op) 11697181Smike{ 11752904Sshin kadm5_log_context *log_context = &context->log_context; 11852904Sshin kadm5_ret_t kadm_ret; 11952904Sshin 12052904Sshin kadm_ret = kadm5_log_init (context); 12152904Sshin if (kadm_ret) 12252904Sshin return kadm_ret; 12397181Smike 12497181Smike krb5_store_int32 (sp, ++log_context->version); 12597181Smike krb5_store_int32 (sp, time(NULL)); 12652904Sshin krb5_store_int32 (sp, op); 12752904Sshin return 0; 12852904Sshin} 12962587Sitojun 13095023Ssuzstatic kadm5_ret_t 13162587Sitojunkadm5_log_postamble (kadm5_log_context *context, 13262587Sitojun krb5_storage *sp) 13362587Sitojun{ 13452904Sshin krb5_store_int32 (sp, context->version); 13552904Sshin return 0; 13662587Sitojun} 13752904Sshin 13852904Sshin/* 13997181Smike * flush the log record in `sp'. 14097181Smike */ 14197181Smike 14297181Smikestatic kadm5_ret_t 14352904Sshinkadm5_log_flush (kadm5_log_context *log_context, 14452904Sshin krb5_storage *sp) 14597181Smike{ 14662587Sitojun krb5_data data; 14752904Sshin size_t len; 14897181Smike int ret; 14952904Sshin 150100503Sume krb5_storage_to_data(sp, &data); 15197181Smike len = data.length; 15297181Smike ret = write (log_context->log_fd, data.data, len); 15397181Smike if (ret != len) { 15462587Sitojun krb5_data_free(&data); 15597181Smike return errno; 15652904Sshin } 15752904Sshin if (fsync (log_context->log_fd) < 0) { 15852904Sshin krb5_data_free(&data); 15952904Sshin return errno; 16052904Sshin } 16195023Ssuz /* 16262587Sitojun * Try to send a signal to any running `ipropd-master' 16362587Sitojun */ 16452904Sshin sendto (log_context->socket_fd, 16562587Sitojun (void *)&log_context->version, 16652904Sshin sizeof(log_context->version), 16762587Sitojun 0, 16852904Sshin (struct sockaddr *)&log_context->socket_name, 16962587Sitojun sizeof(log_context->socket_name)); 17052904Sshin 17152904Sshin krb5_data_free(&data); 17252904Sshin return 0; 17352904Sshin} 17478064Sume 17578064Sume/* 17652904Sshin * Add a `create' operation to the log. 17752904Sshin */ 17852904Sshin 17952904Sshinkadm5_ret_t 18052904Sshinkadm5_log_create (kadm5_server_context *context, 18152904Sshin hdb_entry *ent) 18252904Sshin{ 18352904Sshin krb5_storage *sp; 18452904Sshin kadm5_ret_t ret; 18552904Sshin krb5_data value; 18695023Ssuz kadm5_log_context *log_context = &context->log_context; 18797181Smike 18862587Sitojun sp = krb5_storage_emem(); 18962587Sitojun ret = hdb_entry2value (context->context, ent, &value); 19062587Sitojun if (ret) { 19162587Sitojun krb5_storage_free(sp); 19262587Sitojun return ret; 19362587Sitojun } 19462587Sitojun ret = kadm5_log_preamble (context, sp, kadm_create); 19562587Sitojun if (ret) { 19697181Smike krb5_data_free (&value); 19762587Sitojun krb5_storage_free(sp); 19862587Sitojun return ret; 19962587Sitojun } 20062587Sitojun krb5_store_int32 (sp, value.length); 20162587Sitojun sp->store(sp, value.data, value.length); 20262587Sitojun krb5_store_int32 (sp, value.length); 20362587Sitojun krb5_data_free (&value); 20462587Sitojun ret = kadm5_log_postamble (log_context, sp); 20552904Sshin if (ret) { 20652904Sshin krb5_storage_free (sp); 20752904Sshin return ret; 20852904Sshin } 20952904Sshin ret = kadm5_log_flush (log_context, sp); 21052904Sshin krb5_storage_free (sp); 21197181Smike if (ret) 21262587Sitojun return ret; 21352904Sshin ret = kadm5_log_end (context); 21452904Sshin return ret; 21562587Sitojun} 21652904Sshin 21752904Sshin/* 21862587Sitojun * Read the data of a create log record from `sp' and change the 21952904Sshin * database. 22052904Sshin */ 22162587Sitojun 22252904Sshinkadm5_ret_t 22352904Sshinkadm5_log_replay_create (kadm5_server_context *context, 22462587Sitojun u_int32_t ver, 22552904Sshin u_int32_t len, 22652904Sshin krb5_storage *sp) 22797181Smike{ 22852904Sshin krb5_error_code ret; 22952904Sshin krb5_data data; 23052904Sshin hdb_entry ent; 23197181Smike 23252904Sshin krb5_data_alloc (&data, len); 23352904Sshin sp->fetch (sp, data.data, len); 23452904Sshin ret = hdb_value2entry (context->context, &data, &ent); 23597181Smike krb5_data_free(&data); 23652904Sshin if (ret) 23752904Sshin return ret; 23852904Sshin ret = context->db->store(context->context, context->db, 0, &ent); 23953877Sitojun hdb_free_entry (context->context, &ent); 24053877Sitojun return ret; 24153877Sitojun} 24252904Sshin 24353877Sitojun/* 24462587Sitojun * Add a `delete' operation to the log. 24562587Sitojun */ 24653877Sitojun 24797181Smikekadm5_ret_t 24862587Sitojunkadm5_log_delete (kadm5_server_context *context, 24962587Sitojun krb5_principal princ) 25053877Sitojun{ 25197181Smike krb5_storage *sp; 25252904Sshin kadm5_ret_t ret; 25378064Sume off_t off; 25478064Sume off_t len; 25578064Sume kadm5_log_context *log_context = &context->log_context; 25678064Sume 25778064Sume sp = krb5_storage_emem(); 25878064Sume ret = kadm5_log_preamble (context, sp, kadm_delete); 25978064Sume if (ret) { 26078064Sume krb5_storage_free(sp); 26152904Sshin return ret; 26252904Sshin } 26352904Sshin krb5_store_int32 (sp, 0); 26462587Sitojun off = sp->seek (sp, 0, SEEK_CUR); 26578064Sume krb5_store_principal (sp, princ); 26678064Sume len = sp->seek (sp, 0, SEEK_CUR) - off; 26778064Sume sp->seek(sp, -(len + 4), SEEK_CUR); 26878064Sume krb5_store_int32 (sp, len); 26952904Sshin sp->seek(sp, len, SEEK_CUR); 27052904Sshin krb5_store_int32 (sp, len); 27152904Sshin if (ret) { 27252904Sshin krb5_storage_free (sp); 27362587Sitojun return ret; 27478064Sume } 27578064Sume ret = kadm5_log_postamble (log_context, sp); 27678064Sume if (ret) { 27778064Sume krb5_storage_free (sp); 27852904Sshin return ret; 27952904Sshin } 28052904Sshin ret = kadm5_log_flush (log_context, sp); 28152904Sshin krb5_storage_free (sp); 28262587Sitojun if (ret) 28378064Sume return ret; 28478064Sume ret = kadm5_log_end (context); 28578064Sume return ret; 28678064Sume} 28778064Sume 28852904Sshin/* 28952904Sshin * Read a `delete' log operation from `sp' and apply it. 29052904Sshin */ 29152904Sshin 29262587Sitojunkadm5_ret_t 29378064Sumekadm5_log_replay_delete (kadm5_server_context *context, 29478064Sume u_int32_t ver, 29578064Sume u_int32_t len, 29652904Sshin krb5_storage *sp) 29752904Sshin{ 29852904Sshin krb5_error_code ret; 29952904Sshin hdb_entry ent; 30052904Sshin 30195023Ssuz krb5_ret_principal (sp, &ent.principal); 30262587Sitojun 30362587Sitojun ret = context->db->remove(context->context, context->db, &ent); 30462587Sitojun krb5_free_principal (context->context, ent.principal); 30562587Sitojun return ret; 30662587Sitojun} 30752904Sshin 30862587Sitojun/* 30962587Sitojun * Add a `rename' operation to the log. 31062587Sitojun */ 31162587Sitojun 31262587Sitojunkadm5_ret_t 31352904Sshinkadm5_log_rename (kadm5_server_context *context, 31452904Sshin krb5_principal source, 31552904Sshin hdb_entry *ent) 31652904Sshin{ 31752904Sshin krb5_storage *sp; 31852904Sshin kadm5_ret_t ret; 31962587Sitojun off_t off; 32052904Sshin off_t len; 32162587Sitojun krb5_data value; 32252904Sshin kadm5_log_context *log_context = &context->log_context; 32352904Sshin 32452904Sshin sp = krb5_storage_emem(); 32552904Sshin ret = hdb_entry2value (context->context, ent, &value); 32652904Sshin if (ret) { 32752904Sshin krb5_storage_free(sp); 32852904Sshin return ret; 32995023Ssuz } 33062587Sitojun ret = kadm5_log_preamble (context, sp, kadm_rename); 33152904Sshin if (ret) { 33262587Sitojun krb5_storage_free(sp); 33352904Sshin krb5_data_free (&value); 33452904Sshin return ret; 33552904Sshin } 33652904Sshin krb5_store_int32 (sp, 0); 33752904Sshin off = sp->seek (sp, 0, SEEK_CUR); 33895023Ssuz krb5_store_principal (sp, source); 33962587Sitojun sp->store(sp, value.data, value.length); 34052904Sshin krb5_data_free (&value); 34152904Sshin len = sp->seek (sp, 0, SEEK_CUR) - off; 34262587Sitojun 34352904Sshin sp->seek(sp, -(len + 4), SEEK_CUR); 34452904Sshin krb5_store_int32 (sp, len); 34562587Sitojun sp->seek(sp, len, SEEK_CUR); 34652904Sshin krb5_store_int32 (sp, len); 34752904Sshin if (ret) { 34862587Sitojun krb5_storage_free (sp); 34952904Sshin return ret; 35052904Sshin } 35162587Sitojun ret = kadm5_log_postamble (log_context, sp); 35252904Sshin if (ret) { 35352904Sshin krb5_storage_free (sp); 35452904Sshin return ret; 35562587Sitojun } 35652904Sshin ret = kadm5_log_flush (log_context, sp); 35752904Sshin krb5_storage_free (sp); 35862587Sitojun if (ret) 35952904Sshin return ret; 36052904Sshin ret = kadm5_log_end (context); 36162587Sitojun return ret; 36252904Sshin} 36352904Sshin 36462587Sitojun/* 36552904Sshin * Read a `rename' log operation from `sp' and apply it. 36652904Sshin */ 36762587Sitojun 36852904Sshinkadm5_ret_t 36952904Sshinkadm5_log_replay_rename (kadm5_server_context *context, 37052904Sshin u_int32_t ver, 37152904Sshin u_int32_t len, 37295023Ssuz krb5_storage *sp) 37378064Sume{ 37452904Sshin krb5_error_code ret; 37552904Sshin krb5_principal source; 37662587Sitojun hdb_entry source_ent, target_ent; 37752904Sshin krb5_data value; 37852904Sshin off_t off; 37952904Sshin size_t princ_len, data_len; 38078064Sume 38178064Sume off = sp->seek(sp, 0, SEEK_CUR); 38278064Sume krb5_ret_principal (sp, &source); 38378064Sume princ_len = sp->seek(sp, 0, SEEK_CUR) - off; 38478064Sume data_len = len - princ_len; 38578064Sume krb5_data_alloc (&value, data_len); 38678064Sume sp->fetch (sp, value.data, data_len); 38778064Sume ret = hdb_value2entry (context->context, &value, &target_ent); 38852904Sshin krb5_data_free(&value); 38952904Sshin if (ret) { 39052904Sshin krb5_free_principal (context->context, source); 39197181Smike return ret; 39252904Sshin } 39352904Sshin ret = context->db->store (context->context, context->db, 0, &target_ent); 39452904Sshin hdb_free_entry (context->context, &target_ent); 39552904Sshin if (ret) { 39652904Sshin krb5_free_principal (context->context, source); 39752904Sshin return ret; 39852904Sshin } 39952904Sshin source_ent.principal = source; 40052904Sshin ret = context->db->remove (context->context, context->db, &source_ent); 40152904Sshin krb5_free_principal (context->context, source); 40297181Smike return ret; 40397181Smike} 404100688Sume 405100688Sume 406100688Sume/* 40797181Smike * Add a `modify' operation to the log. 40897181Smike */ 40997181Smike 41097181Smikekadm5_ret_t 41152904Sshinkadm5_log_modify (kadm5_server_context *context, 41262587Sitojun hdb_entry *ent, 41362587Sitojun u_int32_t mask) 41462587Sitojun{ 41562587Sitojun krb5_storage *sp; 41662587Sitojun kadm5_ret_t ret; 41762587Sitojun krb5_data value; 41862587Sitojun u_int32_t len; 41962587Sitojun kadm5_log_context *log_context = &context->log_context; 42062587Sitojun 42162587Sitojun sp = krb5_storage_emem(); 42278064Sume ret = hdb_entry2value (context->context, ent, &value); 42378064Sume if (ret) { 42462587Sitojun krb5_storage_free(sp); 42562587Sitojun return ret; 42662587Sitojun } 42762587Sitojun ret = kadm5_log_preamble (context, sp, kadm_modify); 42862587Sitojun if (ret) { 42962587Sitojun krb5_data_free (&value); 43078064Sume krb5_storage_free(sp); 43162587Sitojun return ret; 43278064Sume } 43378064Sume len = value.length + 4; 43478064Sume krb5_store_int32 (sp, len); 43552904Sshin krb5_store_int32 (sp, mask); 43695023Ssuz sp->store(sp, value.data, value.length); 43762587Sitojun krb5_data_free (&value); 43878064Sume krb5_store_int32 (sp, len); 43962587Sitojun if (ret) { 44052904Sshin krb5_storage_free (sp); 44195023Ssuz return ret; 44262587Sitojun } 44362587Sitojun ret = kadm5_log_postamble (log_context, sp); 44462587Sitojun if (ret) { 44562587Sitojun krb5_storage_free (sp); 44662587Sitojun return ret; 44778064Sume } 44878064Sume ret = kadm5_log_flush (log_context, sp); 44965124Sitojun krb5_storage_free (sp); 45052904Sshin if (ret) 45162587Sitojun return ret; 45262587Sitojun ret = kadm5_log_end (context); 45362587Sitojun return ret; 45452904Sshin} 45552904Sshin 45652904Sshin/* 45752904Sshin * Read a `modify' log operation from `sp' and apply it. 45895023Ssuz */ 45995023Ssuz 46052904Sshinkadm5_ret_t 46152904Sshinkadm5_log_replay_modify (kadm5_server_context *context, 46252904Sshin u_int32_t ver, 46352904Sshin u_int32_t len, 46452904Sshin krb5_storage *sp) 46562587Sitojun{ 46662587Sitojun krb5_error_code ret; 46752904Sshin int32_t mask; 46852904Sshin krb5_data value; 46952904Sshin hdb_entry ent, log_ent; 47052904Sshin 47152904Sshin krb5_ret_int32 (sp, &mask); 47252904Sshin len -= 4; 47362587Sitojun krb5_data_alloc (&value, len); 47462587Sitojun sp->fetch (sp, value.data, len); 47552904Sshin ret = hdb_value2entry (context->context, &value, &log_ent); 47652904Sshin krb5_data_free(&value); 47752904Sshin if (ret) 47852904Sshin return ret; 47952904Sshin ent.principal = log_ent.principal; 48052904Sshin log_ent.principal = NULL; 48152904Sshin ret = context->db->fetch(context->context, context->db, 48252904Sshin HDB_F_DECRYPT, &ent); 48352904Sshin if (ret) 48452904Sshin return ret; 48552904Sshin if (mask & KADM5_PRINC_EXPIRE_TIME) { 48652904Sshin if (ent.valid_end == NULL) 48752904Sshin ent.valid_end = malloc(sizeof(*ent.valid_end)); 48852904Sshin *ent.valid_end = *log_ent.valid_end; 48952904Sshin } 49052904Sshin if (mask & KADM5_PW_EXPIRATION) { 49162587Sitojun if (ent.pw_end == NULL) 49252904Sshin ent.pw_end = malloc(sizeof(*ent.pw_end)); 49362587Sitojun *ent.pw_end = *log_ent.pw_end; 49452904Sshin } 49552904Sshin if (mask & KADM5_LAST_PWD_CHANGE) { 49652904Sshin abort (); /* XXX */ 49752904Sshin } 49852904Sshin if (mask & KADM5_ATTRIBUTES) { 49952904Sshin ent.flags = log_ent.flags; 50052904Sshin } 50152904Sshin if (mask & KADM5_MAX_LIFE) { 50252904Sshin if (ent.max_life == NULL) 50352904Sshin ent.max_life = malloc (sizeof(*ent.max_life)); 50452904Sshin *ent.max_life = *log_ent.max_life; 50552904Sshin } 50652904Sshin if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) { 50752904Sshin if (ent.modified_by == NULL) { 50852904Sshin ent.modified_by = malloc(sizeof(*ent.modified_by)); 50952904Sshin } else 51052904Sshin free_Event(ent.modified_by); 51152904Sshin copy_Event(log_ent.modified_by, ent.modified_by); 51252904Sshin } 51352904Sshin if (mask & KADM5_KVNO) { 51452904Sshin ent.kvno = log_ent.kvno; 51552904Sshin } 51652904Sshin if (mask & KADM5_MKVNO) { 51752904Sshin abort (); /* XXX */ 51852904Sshin } 51952904Sshin if (mask & KADM5_AUX_ATTRIBUTES) { 52052904Sshin abort (); /* XXX */ 52152904Sshin } 52252904Sshin if (mask & KADM5_POLICY) { 52352904Sshin abort (); /* XXX */ 52452904Sshin } 52552904Sshin if (mask & KADM5_POLICY_CLR) { 52652904Sshin abort (); /* XXX */ 52752904Sshin } 52852904Sshin if (mask & KADM5_MAX_RLIFE) { 52952904Sshin if (ent.max_renew == NULL) 53052904Sshin ent.max_renew = malloc (sizeof(*ent.max_renew)); 53152904Sshin *ent.max_renew = *log_ent.max_renew; 53252904Sshin } 53352904Sshin if (mask & KADM5_LAST_SUCCESS) { 53452904Sshin abort (); /* XXX */ 53552904Sshin } 53652904Sshin if (mask & KADM5_LAST_FAILED) { 53752904Sshin abort (); /* XXX */ 53852904Sshin } 53952904Sshin if (mask & KADM5_FAIL_AUTH_COUNT) { 54052904Sshin abort (); /* XXX */ 54152904Sshin } 54252904Sshin if (mask & KADM5_KEY_DATA) { 54362587Sitojun size_t len; 54462587Sitojun int i; 54562587Sitojun 54652904Sshin for (i = 0; i < ent.keys.len; ++i) 54762587Sitojun free_Key(&ent.keys.val[i]); 54852904Sshin free (ent.keys.val); 54962587Sitojun 55062587Sitojun len = log_ent.keys.len; 55162587Sitojun 55262587Sitojun ent.keys.len = len; 55362587Sitojun ent.keys.val = malloc(len * sizeof(*ent.keys.val)); 55462587Sitojun for (i = 0; i < ent.keys.len; ++i) 55562587Sitojun copy_Key(&log_ent.keys.val[i], 55662587Sitojun &ent.keys.val[i]); 55762587Sitojun } 55862587Sitojun ret = context->db->store(context->context, context->db, 55962587Sitojun HDB_F_REPLACE, &ent); 56062587Sitojun hdb_free_entry (context->context, &ent); 56162587Sitojun hdb_free_entry (context->context, &log_ent); 56262587Sitojun return ret; 56362587Sitojun} 56462587Sitojun 56562587Sitojun/* 56662587Sitojun * Call `func' for each log record in the log in `context' 56795023Ssuz */ 56862587Sitojun 56962604Sitojunkadm5_ret_t 57078064Sumekadm5_log_foreach (kadm5_server_context *context, 57162604Sitojun void (*func)(kadm5_server_context *server_context, 57262604Sitojun u_int32_t ver, 57362604Sitojun time_t timestamp, 57478064Sume enum kadm_ops op, 57578064Sume u_int32_t len, 57678064Sume krb5_storage *sp)) 57778064Sume{ 57878064Sume int fd = context->log_context.log_fd; 57978064Sume krb5_storage *sp; 58078064Sume 58152904Sshin lseek (fd, 0, SEEK_SET); 58265124Sitojun sp = krb5_storage_from_fd (fd); 58378064Sume for (;;) { 58478064Sume int32_t ver, timestamp, op, len; 58553541Sshin 58653541Sshin if(krb5_ret_int32 (sp, &ver) != 0) 58753541Sshin break; 58878064Sume krb5_ret_int32 (sp, ×tamp); 58978064Sume krb5_ret_int32 (sp, &op); 59078064Sume krb5_ret_int32 (sp, &len); 59178064Sume (*func)(context, ver, timestamp, op, len, sp); 59253541Sshin sp->seek(sp, 8, SEEK_CUR); 59352904Sshin } 59478064Sume return 0; 59552904Sshin} 59662587Sitojun 59752904Sshin/* 59852904Sshin * Go to end of log. 59952904Sshin */ 60052904Sshin 60178064Sumekrb5_storage * 60278064Sumekadm5_log_goto_end (int fd) 60392700Sdarrenr{ 60452904Sshin krb5_storage *sp; 60552904Sshin 60652904Sshin sp = krb5_storage_from_fd (fd); 60752904Sshin sp->seek(sp, 0, SEEK_END); 60852904Sshin return sp; 60952904Sshin} 61052904Sshin 61152904Sshin/* 61278064Sume * Return previous log entry. 61378064Sume */ 61478064Sume 61583934Sbrookskadm5_ret_t 61683934Sbrookskadm5_log_previous (krb5_storage *sp, 61752904Sshin u_int32_t *ver, 61852904Sshin time_t *timestamp, 619102227Smike enum kadm_ops *op, 620102227Smike u_int32_t *len) 621102227Smike{ 62297181Smike off_t off; 62397181Smike int32_t tmp; 62452904Sshin 62552904Sshin sp->seek(sp, -8, SEEK_CUR); 62652904Sshin krb5_ret_int32 (sp, &tmp); 62778064Sume *len = tmp; 62878064Sume krb5_ret_int32 (sp, &tmp); 62997181Smike *ver = tmp; 63078064Sume off = 24 + *len; 63197181Smike sp->seek(sp, -off, SEEK_CUR); 63297181Smike krb5_ret_int32 (sp, &tmp); 63397181Smike assert(tmp == *ver); 63452904Sshin krb5_ret_int32 (sp, &tmp); 63578064Sume *timestamp = tmp; 63678064Sume krb5_ret_int32 (sp, &tmp); 63778064Sume *op = tmp; 63878064Sume krb5_ret_int32 (sp, &tmp); 63978064Sume assert(tmp == *len); 64078064Sume return 0; 64178064Sume} 64278064Sume 64378064Sume/* 64478064Sume * Replay a record from the log 64578064Sume */ 64678064Sume 64778064Sumekadm5_ret_t 64897181Smikekadm5_log_replay (kadm5_server_context *context, 64997181Smike enum kadm_ops op, 65078064Sume u_int32_t ver, 65178064Sume u_int32_t len, 65278064Sume krb5_storage *sp) 65397181Smike{ 65478064Sume switch (op) { 65597181Smike case kadm_create : 65678064Sume return kadm5_log_replay_create (context, ver, len, sp); 65778064Sume case kadm_delete : 65878064Sume return kadm5_log_replay_delete (context, ver, len, sp); 65978064Sume case kadm_rename : 66078064Sume return kadm5_log_replay_rename (context, ver, len, sp); 66178064Sume case kadm_modify : 66278064Sume return kadm5_log_replay_modify (context, ver, len, sp); 66378064Sume default : 66452904Sshin return KADM5_FAILURE; 66552904Sshin } 66697181Smike} 66797181Smike