log.c revision 72445
155682Smarkm/* 272445Sassar * Copyright (c) 1997 - 2000 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadm5_locl.h" 3555682Smarkm 3672445SassarRCSID("$Id: log.c,v 1.18 2000/07/24 04:32:17 assar Exp $"); 3755682Smarkm 3855682Smarkm/* 3955682Smarkm * A log record consists of: 4055682Smarkm * 4155682Smarkm * version number 4 bytes 4255682Smarkm * time in seconds 4 bytes 4355682Smarkm * operation (enum kadm_ops) 4 bytes 4455682Smarkm * length of record 4 bytes 4555682Smarkm * data... n bytes 4655682Smarkm * length of record 4 bytes 4755682Smarkm * version number 4 bytes 4855682Smarkm * 4955682Smarkm */ 5055682Smarkm 5155682Smarkmkadm5_ret_t 5272445Sassarkadm5_log_get_version_fd (int fd, 5372445Sassar u_int32_t *ver) 5455682Smarkm{ 5555682Smarkm int ret; 5655682Smarkm krb5_storage *sp; 5755682Smarkm int32_t old_version; 5855682Smarkm 5955682Smarkm ret = lseek (fd, 0, SEEK_END); 6055682Smarkm if(ret < 0) 6155682Smarkm return errno; 6255682Smarkm if(ret == 0) { 6355682Smarkm *ver = 0; 6455682Smarkm return 0; 6555682Smarkm } 6655682Smarkm sp = krb5_storage_from_fd (fd); 6755682Smarkm sp->seek(sp, -4, SEEK_CUR); 6855682Smarkm krb5_ret_int32 (sp, &old_version); 6955682Smarkm *ver = old_version; 7055682Smarkm krb5_storage_free(sp); 7155682Smarkm lseek (fd, 0, SEEK_END); 7255682Smarkm return 0; 7355682Smarkm} 7455682Smarkm 7555682Smarkmkadm5_ret_t 7672445Sassarkadm5_log_get_version (kadm5_server_context *context, u_int32_t *ver) 7772445Sassar{ 7872445Sassar return kadm5_log_get_version_fd (context->log_context.log_fd, ver); 7972445Sassar} 8072445Sassar 8172445Sassarkadm5_ret_t 8272445Sassarkadm5_log_set_version (kadm5_server_context *context, u_int32_t vno) 8372445Sassar{ 8472445Sassar kadm5_log_context *log_context = &context->log_context; 8572445Sassar 8672445Sassar log_context->version = vno; 8772445Sassar return 0; 8872445Sassar} 8972445Sassar 9072445Sassarkadm5_ret_t 9155682Smarkmkadm5_log_init (kadm5_server_context *context) 9255682Smarkm{ 9355682Smarkm int fd; 9455682Smarkm kadm5_ret_t ret; 9555682Smarkm kadm5_log_context *log_context = &context->log_context; 9655682Smarkm 9755682Smarkm if (log_context->log_fd != -1) 9855682Smarkm return 0; 9955682Smarkm fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600); 10055682Smarkm if (fd < 0) 10155682Smarkm return errno; 10255682Smarkm if (flock (fd, LOCK_EX) < 0) { 10355682Smarkm close (fd); 10455682Smarkm return errno; 10555682Smarkm } 10655682Smarkm 10772445Sassar ret = kadm5_log_get_version_fd (fd, &log_context->version); 10855682Smarkm if (ret) 10955682Smarkm return ret; 11055682Smarkm 11155682Smarkm log_context->log_fd = fd; 11255682Smarkm return 0; 11355682Smarkm} 11455682Smarkm 11555682Smarkmkadm5_ret_t 11672445Sassarkadm5_log_reinit (kadm5_server_context *context) 11772445Sassar{ 11872445Sassar int fd; 11972445Sassar kadm5_log_context *log_context = &context->log_context; 12072445Sassar 12172445Sassar if (log_context->log_fd != -1) { 12272445Sassar close (log_context->log_fd); 12372445Sassar log_context->log_fd = -1; 12472445Sassar } 12572445Sassar fd = open (log_context->log_file, O_RDWR | O_CREAT | O_TRUNC, 0600); 12672445Sassar if (fd < 0) 12772445Sassar return errno; 12872445Sassar if (flock (fd, LOCK_EX) < 0) { 12972445Sassar close (fd); 13072445Sassar return errno; 13172445Sassar } 13272445Sassar 13372445Sassar log_context->version = 0; 13472445Sassar log_context->log_fd = fd; 13572445Sassar return 0; 13672445Sassar} 13772445Sassar 13872445Sassar 13972445Sassarkadm5_ret_t 14055682Smarkmkadm5_log_end (kadm5_server_context *context) 14155682Smarkm{ 14255682Smarkm kadm5_log_context *log_context = &context->log_context; 14355682Smarkm int fd = log_context->log_fd; 14455682Smarkm 14555682Smarkm flock (fd, LOCK_UN); 14655682Smarkm close(fd); 14755682Smarkm log_context->log_fd = -1; 14855682Smarkm return 0; 14955682Smarkm} 15055682Smarkm 15155682Smarkmstatic kadm5_ret_t 15255682Smarkmkadm5_log_preamble (kadm5_server_context *context, 15355682Smarkm krb5_storage *sp, 15455682Smarkm enum kadm_ops op) 15555682Smarkm{ 15655682Smarkm kadm5_log_context *log_context = &context->log_context; 15755682Smarkm kadm5_ret_t kadm_ret; 15855682Smarkm 15955682Smarkm kadm_ret = kadm5_log_init (context); 16055682Smarkm if (kadm_ret) 16155682Smarkm return kadm_ret; 16255682Smarkm 16355682Smarkm krb5_store_int32 (sp, ++log_context->version); 16455682Smarkm krb5_store_int32 (sp, time(NULL)); 16555682Smarkm krb5_store_int32 (sp, op); 16655682Smarkm return 0; 16755682Smarkm} 16855682Smarkm 16955682Smarkmstatic kadm5_ret_t 17055682Smarkmkadm5_log_postamble (kadm5_log_context *context, 17155682Smarkm krb5_storage *sp) 17255682Smarkm{ 17355682Smarkm krb5_store_int32 (sp, context->version); 17455682Smarkm return 0; 17555682Smarkm} 17655682Smarkm 17755682Smarkm/* 17855682Smarkm * flush the log record in `sp'. 17955682Smarkm */ 18055682Smarkm 18155682Smarkmstatic kadm5_ret_t 18255682Smarkmkadm5_log_flush (kadm5_log_context *log_context, 18355682Smarkm krb5_storage *sp) 18455682Smarkm{ 18555682Smarkm krb5_data data; 18655682Smarkm size_t len; 18755682Smarkm int ret; 18855682Smarkm 18955682Smarkm krb5_storage_to_data(sp, &data); 19055682Smarkm len = data.length; 19155682Smarkm ret = write (log_context->log_fd, data.data, len); 19255682Smarkm if (ret != len) { 19355682Smarkm krb5_data_free(&data); 19455682Smarkm return errno; 19555682Smarkm } 19655682Smarkm if (fsync (log_context->log_fd) < 0) { 19755682Smarkm krb5_data_free(&data); 19855682Smarkm return errno; 19955682Smarkm } 20055682Smarkm /* 20155682Smarkm * Try to send a signal to any running `ipropd-master' 20255682Smarkm */ 20355682Smarkm sendto (log_context->socket_fd, 20455682Smarkm (void *)&log_context->version, 20555682Smarkm sizeof(log_context->version), 20655682Smarkm 0, 20755682Smarkm (struct sockaddr *)&log_context->socket_name, 20855682Smarkm sizeof(log_context->socket_name)); 20955682Smarkm 21055682Smarkm krb5_data_free(&data); 21155682Smarkm return 0; 21255682Smarkm} 21355682Smarkm 21455682Smarkm/* 21555682Smarkm * Add a `create' operation to the log. 21655682Smarkm */ 21755682Smarkm 21855682Smarkmkadm5_ret_t 21955682Smarkmkadm5_log_create (kadm5_server_context *context, 22055682Smarkm hdb_entry *ent) 22155682Smarkm{ 22255682Smarkm krb5_storage *sp; 22355682Smarkm kadm5_ret_t ret; 22455682Smarkm krb5_data value; 22555682Smarkm kadm5_log_context *log_context = &context->log_context; 22655682Smarkm 22755682Smarkm sp = krb5_storage_emem(); 22855682Smarkm ret = hdb_entry2value (context->context, ent, &value); 22955682Smarkm if (ret) { 23055682Smarkm krb5_storage_free(sp); 23155682Smarkm return ret; 23255682Smarkm } 23355682Smarkm ret = kadm5_log_preamble (context, sp, kadm_create); 23455682Smarkm if (ret) { 23555682Smarkm krb5_data_free (&value); 23655682Smarkm krb5_storage_free(sp); 23755682Smarkm return ret; 23855682Smarkm } 23955682Smarkm krb5_store_int32 (sp, value.length); 24055682Smarkm sp->store(sp, value.data, value.length); 24155682Smarkm krb5_store_int32 (sp, value.length); 24255682Smarkm krb5_data_free (&value); 24355682Smarkm ret = kadm5_log_postamble (log_context, sp); 24455682Smarkm if (ret) { 24555682Smarkm krb5_storage_free (sp); 24655682Smarkm return ret; 24755682Smarkm } 24855682Smarkm ret = kadm5_log_flush (log_context, sp); 24955682Smarkm krb5_storage_free (sp); 25055682Smarkm if (ret) 25155682Smarkm return ret; 25255682Smarkm ret = kadm5_log_end (context); 25355682Smarkm return ret; 25455682Smarkm} 25555682Smarkm 25655682Smarkm/* 25755682Smarkm * Read the data of a create log record from `sp' and change the 25855682Smarkm * database. 25955682Smarkm */ 26055682Smarkm 26155682Smarkmkadm5_ret_t 26255682Smarkmkadm5_log_replay_create (kadm5_server_context *context, 26355682Smarkm u_int32_t ver, 26455682Smarkm u_int32_t len, 26555682Smarkm krb5_storage *sp) 26655682Smarkm{ 26755682Smarkm krb5_error_code ret; 26855682Smarkm krb5_data data; 26955682Smarkm hdb_entry ent; 27055682Smarkm 27155682Smarkm krb5_data_alloc (&data, len); 27255682Smarkm sp->fetch (sp, data.data, len); 27355682Smarkm ret = hdb_value2entry (context->context, &data, &ent); 27455682Smarkm krb5_data_free(&data); 27555682Smarkm if (ret) 27655682Smarkm return ret; 27755682Smarkm ret = context->db->store(context->context, context->db, 0, &ent); 27855682Smarkm hdb_free_entry (context->context, &ent); 27955682Smarkm return ret; 28055682Smarkm} 28155682Smarkm 28255682Smarkm/* 28355682Smarkm * Add a `delete' operation to the log. 28455682Smarkm */ 28555682Smarkm 28655682Smarkmkadm5_ret_t 28755682Smarkmkadm5_log_delete (kadm5_server_context *context, 28855682Smarkm krb5_principal princ) 28955682Smarkm{ 29055682Smarkm krb5_storage *sp; 29155682Smarkm kadm5_ret_t ret; 29255682Smarkm off_t off; 29355682Smarkm off_t len; 29455682Smarkm kadm5_log_context *log_context = &context->log_context; 29555682Smarkm 29655682Smarkm sp = krb5_storage_emem(); 29755682Smarkm ret = kadm5_log_preamble (context, sp, kadm_delete); 29855682Smarkm if (ret) { 29955682Smarkm krb5_storage_free(sp); 30055682Smarkm return ret; 30155682Smarkm } 30255682Smarkm krb5_store_int32 (sp, 0); 30355682Smarkm off = sp->seek (sp, 0, SEEK_CUR); 30455682Smarkm krb5_store_principal (sp, princ); 30555682Smarkm len = sp->seek (sp, 0, SEEK_CUR) - off; 30655682Smarkm sp->seek(sp, -(len + 4), SEEK_CUR); 30755682Smarkm krb5_store_int32 (sp, len); 30855682Smarkm sp->seek(sp, len, SEEK_CUR); 30955682Smarkm krb5_store_int32 (sp, len); 31055682Smarkm if (ret) { 31155682Smarkm krb5_storage_free (sp); 31255682Smarkm return ret; 31355682Smarkm } 31455682Smarkm ret = kadm5_log_postamble (log_context, sp); 31555682Smarkm if (ret) { 31655682Smarkm krb5_storage_free (sp); 31755682Smarkm return ret; 31855682Smarkm } 31955682Smarkm ret = kadm5_log_flush (log_context, sp); 32055682Smarkm krb5_storage_free (sp); 32155682Smarkm if (ret) 32255682Smarkm return ret; 32355682Smarkm ret = kadm5_log_end (context); 32455682Smarkm return ret; 32555682Smarkm} 32655682Smarkm 32755682Smarkm/* 32855682Smarkm * Read a `delete' log operation from `sp' and apply it. 32955682Smarkm */ 33055682Smarkm 33155682Smarkmkadm5_ret_t 33255682Smarkmkadm5_log_replay_delete (kadm5_server_context *context, 33355682Smarkm u_int32_t ver, 33455682Smarkm u_int32_t len, 33555682Smarkm krb5_storage *sp) 33655682Smarkm{ 33755682Smarkm krb5_error_code ret; 33855682Smarkm hdb_entry ent; 33955682Smarkm 34055682Smarkm krb5_ret_principal (sp, &ent.principal); 34155682Smarkm 34255682Smarkm ret = context->db->remove(context->context, context->db, &ent); 34355682Smarkm krb5_free_principal (context->context, ent.principal); 34455682Smarkm return ret; 34555682Smarkm} 34655682Smarkm 34755682Smarkm/* 34855682Smarkm * Add a `rename' operation to the log. 34955682Smarkm */ 35055682Smarkm 35155682Smarkmkadm5_ret_t 35255682Smarkmkadm5_log_rename (kadm5_server_context *context, 35355682Smarkm krb5_principal source, 35455682Smarkm hdb_entry *ent) 35555682Smarkm{ 35655682Smarkm krb5_storage *sp; 35755682Smarkm kadm5_ret_t ret; 35855682Smarkm off_t off; 35955682Smarkm off_t len; 36055682Smarkm krb5_data value; 36155682Smarkm kadm5_log_context *log_context = &context->log_context; 36255682Smarkm 36355682Smarkm sp = krb5_storage_emem(); 36455682Smarkm ret = hdb_entry2value (context->context, ent, &value); 36555682Smarkm if (ret) { 36655682Smarkm krb5_storage_free(sp); 36755682Smarkm return ret; 36855682Smarkm } 36955682Smarkm ret = kadm5_log_preamble (context, sp, kadm_rename); 37055682Smarkm if (ret) { 37155682Smarkm krb5_storage_free(sp); 37255682Smarkm krb5_data_free (&value); 37355682Smarkm return ret; 37455682Smarkm } 37555682Smarkm krb5_store_int32 (sp, 0); 37655682Smarkm off = sp->seek (sp, 0, SEEK_CUR); 37755682Smarkm krb5_store_principal (sp, source); 37855682Smarkm sp->store(sp, value.data, value.length); 37955682Smarkm krb5_data_free (&value); 38055682Smarkm len = sp->seek (sp, 0, SEEK_CUR) - off; 38155682Smarkm 38255682Smarkm sp->seek(sp, -(len + 4), SEEK_CUR); 38355682Smarkm krb5_store_int32 (sp, len); 38455682Smarkm sp->seek(sp, len, SEEK_CUR); 38555682Smarkm krb5_store_int32 (sp, len); 38655682Smarkm if (ret) { 38755682Smarkm krb5_storage_free (sp); 38855682Smarkm return ret; 38955682Smarkm } 39055682Smarkm ret = kadm5_log_postamble (log_context, sp); 39155682Smarkm if (ret) { 39255682Smarkm krb5_storage_free (sp); 39355682Smarkm return ret; 39455682Smarkm } 39555682Smarkm ret = kadm5_log_flush (log_context, sp); 39655682Smarkm krb5_storage_free (sp); 39755682Smarkm if (ret) 39855682Smarkm return ret; 39955682Smarkm ret = kadm5_log_end (context); 40055682Smarkm return ret; 40155682Smarkm} 40255682Smarkm 40355682Smarkm/* 40455682Smarkm * Read a `rename' log operation from `sp' and apply it. 40555682Smarkm */ 40655682Smarkm 40755682Smarkmkadm5_ret_t 40855682Smarkmkadm5_log_replay_rename (kadm5_server_context *context, 40955682Smarkm u_int32_t ver, 41055682Smarkm u_int32_t len, 41155682Smarkm krb5_storage *sp) 41255682Smarkm{ 41355682Smarkm krb5_error_code ret; 41455682Smarkm krb5_principal source; 41555682Smarkm hdb_entry source_ent, target_ent; 41655682Smarkm krb5_data value; 41755682Smarkm off_t off; 41855682Smarkm size_t princ_len, data_len; 41955682Smarkm 42055682Smarkm off = sp->seek(sp, 0, SEEK_CUR); 42155682Smarkm krb5_ret_principal (sp, &source); 42255682Smarkm princ_len = sp->seek(sp, 0, SEEK_CUR) - off; 42355682Smarkm data_len = len - princ_len; 42455682Smarkm krb5_data_alloc (&value, data_len); 42555682Smarkm sp->fetch (sp, value.data, data_len); 42655682Smarkm ret = hdb_value2entry (context->context, &value, &target_ent); 42755682Smarkm krb5_data_free(&value); 42855682Smarkm if (ret) { 42955682Smarkm krb5_free_principal (context->context, source); 43055682Smarkm return ret; 43155682Smarkm } 43255682Smarkm ret = context->db->store (context->context, context->db, 0, &target_ent); 43355682Smarkm hdb_free_entry (context->context, &target_ent); 43455682Smarkm if (ret) { 43555682Smarkm krb5_free_principal (context->context, source); 43655682Smarkm return ret; 43755682Smarkm } 43855682Smarkm source_ent.principal = source; 43955682Smarkm ret = context->db->remove (context->context, context->db, &source_ent); 44055682Smarkm krb5_free_principal (context->context, source); 44155682Smarkm return ret; 44255682Smarkm} 44355682Smarkm 44455682Smarkm 44555682Smarkm/* 44655682Smarkm * Add a `modify' operation to the log. 44755682Smarkm */ 44855682Smarkm 44955682Smarkmkadm5_ret_t 45055682Smarkmkadm5_log_modify (kadm5_server_context *context, 45155682Smarkm hdb_entry *ent, 45255682Smarkm u_int32_t mask) 45355682Smarkm{ 45455682Smarkm krb5_storage *sp; 45555682Smarkm kadm5_ret_t ret; 45655682Smarkm krb5_data value; 45755682Smarkm u_int32_t len; 45855682Smarkm kadm5_log_context *log_context = &context->log_context; 45955682Smarkm 46055682Smarkm sp = krb5_storage_emem(); 46155682Smarkm ret = hdb_entry2value (context->context, ent, &value); 46255682Smarkm if (ret) { 46355682Smarkm krb5_storage_free(sp); 46455682Smarkm return ret; 46555682Smarkm } 46655682Smarkm ret = kadm5_log_preamble (context, sp, kadm_modify); 46755682Smarkm if (ret) { 46855682Smarkm krb5_data_free (&value); 46955682Smarkm krb5_storage_free(sp); 47055682Smarkm return ret; 47155682Smarkm } 47255682Smarkm len = value.length + 4; 47355682Smarkm krb5_store_int32 (sp, len); 47455682Smarkm krb5_store_int32 (sp, mask); 47555682Smarkm sp->store(sp, value.data, value.length); 47655682Smarkm krb5_data_free (&value); 47755682Smarkm krb5_store_int32 (sp, len); 47855682Smarkm if (ret) { 47955682Smarkm krb5_storage_free (sp); 48055682Smarkm return ret; 48155682Smarkm } 48255682Smarkm ret = kadm5_log_postamble (log_context, sp); 48355682Smarkm if (ret) { 48455682Smarkm krb5_storage_free (sp); 48555682Smarkm return ret; 48655682Smarkm } 48755682Smarkm ret = kadm5_log_flush (log_context, sp); 48855682Smarkm krb5_storage_free (sp); 48955682Smarkm if (ret) 49055682Smarkm return ret; 49155682Smarkm ret = kadm5_log_end (context); 49255682Smarkm return ret; 49355682Smarkm} 49455682Smarkm 49555682Smarkm/* 49655682Smarkm * Read a `modify' log operation from `sp' and apply it. 49755682Smarkm */ 49855682Smarkm 49955682Smarkmkadm5_ret_t 50055682Smarkmkadm5_log_replay_modify (kadm5_server_context *context, 50155682Smarkm u_int32_t ver, 50255682Smarkm u_int32_t len, 50355682Smarkm krb5_storage *sp) 50455682Smarkm{ 50555682Smarkm krb5_error_code ret; 50655682Smarkm int32_t mask; 50755682Smarkm krb5_data value; 50855682Smarkm hdb_entry ent, log_ent; 50955682Smarkm 51055682Smarkm krb5_ret_int32 (sp, &mask); 51155682Smarkm len -= 4; 51255682Smarkm krb5_data_alloc (&value, len); 51355682Smarkm sp->fetch (sp, value.data, len); 51455682Smarkm ret = hdb_value2entry (context->context, &value, &log_ent); 51555682Smarkm krb5_data_free(&value); 51655682Smarkm if (ret) 51755682Smarkm return ret; 51855682Smarkm ent.principal = log_ent.principal; 51955682Smarkm log_ent.principal = NULL; 52055682Smarkm ret = context->db->fetch(context->context, context->db, 52155682Smarkm HDB_F_DECRYPT, &ent); 52255682Smarkm if (ret) 52355682Smarkm return ret; 52455682Smarkm if (mask & KADM5_PRINC_EXPIRE_TIME) { 52572445Sassar if (log_ent.valid_end == NULL) { 52672445Sassar ent.valid_end = NULL; 52772445Sassar } else { 52872445Sassar if (ent.valid_end == NULL) 52972445Sassar ent.valid_end = malloc(sizeof(*ent.valid_end)); 53072445Sassar *ent.valid_end = *log_ent.valid_end; 53172445Sassar } 53255682Smarkm } 53355682Smarkm if (mask & KADM5_PW_EXPIRATION) { 53472445Sassar if (log_ent.pw_end == NULL) { 53572445Sassar ent.pw_end = NULL; 53672445Sassar } else { 53772445Sassar if (ent.pw_end == NULL) 53872445Sassar ent.pw_end = malloc(sizeof(*ent.pw_end)); 53972445Sassar *ent.pw_end = *log_ent.pw_end; 54072445Sassar } 54155682Smarkm } 54255682Smarkm if (mask & KADM5_LAST_PWD_CHANGE) { 54355682Smarkm abort (); /* XXX */ 54455682Smarkm } 54555682Smarkm if (mask & KADM5_ATTRIBUTES) { 54655682Smarkm ent.flags = log_ent.flags; 54755682Smarkm } 54855682Smarkm if (mask & KADM5_MAX_LIFE) { 54972445Sassar if (log_ent.max_life == NULL) { 55072445Sassar ent.max_life = NULL; 55172445Sassar } else { 55272445Sassar if (ent.max_life == NULL) 55372445Sassar ent.max_life = malloc (sizeof(*ent.max_life)); 55472445Sassar *ent.max_life = *log_ent.max_life; 55572445Sassar } 55655682Smarkm } 55755682Smarkm if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) { 55855682Smarkm if (ent.modified_by == NULL) { 55955682Smarkm ent.modified_by = malloc(sizeof(*ent.modified_by)); 56055682Smarkm } else 56155682Smarkm free_Event(ent.modified_by); 56255682Smarkm copy_Event(log_ent.modified_by, ent.modified_by); 56355682Smarkm } 56455682Smarkm if (mask & KADM5_KVNO) { 56555682Smarkm ent.kvno = log_ent.kvno; 56655682Smarkm } 56755682Smarkm if (mask & KADM5_MKVNO) { 56855682Smarkm abort (); /* XXX */ 56955682Smarkm } 57055682Smarkm if (mask & KADM5_AUX_ATTRIBUTES) { 57155682Smarkm abort (); /* XXX */ 57255682Smarkm } 57355682Smarkm if (mask & KADM5_POLICY) { 57455682Smarkm abort (); /* XXX */ 57555682Smarkm } 57655682Smarkm if (mask & KADM5_POLICY_CLR) { 57755682Smarkm abort (); /* XXX */ 57855682Smarkm } 57955682Smarkm if (mask & KADM5_MAX_RLIFE) { 58072445Sassar if (log_ent.max_renew == NULL) { 58172445Sassar ent.max_renew = NULL; 58272445Sassar } else { 58372445Sassar if (ent.max_renew == NULL) 58472445Sassar ent.max_renew = malloc (sizeof(*ent.max_renew)); 58572445Sassar *ent.max_renew = *log_ent.max_renew; 58672445Sassar } 58755682Smarkm } 58855682Smarkm if (mask & KADM5_LAST_SUCCESS) { 58955682Smarkm abort (); /* XXX */ 59055682Smarkm } 59155682Smarkm if (mask & KADM5_LAST_FAILED) { 59255682Smarkm abort (); /* XXX */ 59355682Smarkm } 59455682Smarkm if (mask & KADM5_FAIL_AUTH_COUNT) { 59555682Smarkm abort (); /* XXX */ 59655682Smarkm } 59755682Smarkm if (mask & KADM5_KEY_DATA) { 59855682Smarkm size_t len; 59955682Smarkm int i; 60055682Smarkm 60155682Smarkm for (i = 0; i < ent.keys.len; ++i) 60255682Smarkm free_Key(&ent.keys.val[i]); 60355682Smarkm free (ent.keys.val); 60455682Smarkm 60555682Smarkm len = log_ent.keys.len; 60655682Smarkm 60755682Smarkm ent.keys.len = len; 60855682Smarkm ent.keys.val = malloc(len * sizeof(*ent.keys.val)); 60955682Smarkm for (i = 0; i < ent.keys.len; ++i) 61055682Smarkm copy_Key(&log_ent.keys.val[i], 61155682Smarkm &ent.keys.val[i]); 61255682Smarkm } 61355682Smarkm ret = context->db->store(context->context, context->db, 61455682Smarkm HDB_F_REPLACE, &ent); 61555682Smarkm hdb_free_entry (context->context, &ent); 61655682Smarkm hdb_free_entry (context->context, &log_ent); 61755682Smarkm return ret; 61855682Smarkm} 61955682Smarkm 62055682Smarkm/* 62172445Sassar * Add a `nop' operation to the log. 62272445Sassar */ 62372445Sassar 62472445Sassarkadm5_ret_t 62572445Sassarkadm5_log_nop (kadm5_server_context *context) 62672445Sassar{ 62772445Sassar krb5_storage *sp; 62872445Sassar kadm5_ret_t ret; 62972445Sassar kadm5_log_context *log_context = &context->log_context; 63072445Sassar 63172445Sassar sp = krb5_storage_emem(); 63272445Sassar ret = kadm5_log_preamble (context, sp, kadm_nop); 63372445Sassar if (ret) { 63472445Sassar krb5_storage_free (sp); 63572445Sassar return ret; 63672445Sassar } 63772445Sassar krb5_store_int32 (sp, 0); 63872445Sassar krb5_store_int32 (sp, 0); 63972445Sassar ret = kadm5_log_postamble (log_context, sp); 64072445Sassar if (ret) { 64172445Sassar krb5_storage_free (sp); 64272445Sassar return ret; 64372445Sassar } 64472445Sassar ret = kadm5_log_flush (log_context, sp); 64572445Sassar krb5_storage_free (sp); 64672445Sassar if (ret) 64772445Sassar return ret; 64872445Sassar ret = kadm5_log_end (context); 64972445Sassar return ret; 65072445Sassar} 65172445Sassar 65272445Sassar/* 65372445Sassar * Read a `nop' log operation from `sp' and apply it. 65472445Sassar */ 65572445Sassar 65672445Sassarkadm5_ret_t 65772445Sassarkadm5_log_replay_nop (kadm5_server_context *context, 65872445Sassar u_int32_t ver, 65972445Sassar u_int32_t len, 66072445Sassar krb5_storage *sp) 66172445Sassar{ 66272445Sassar return 0; 66372445Sassar} 66472445Sassar 66572445Sassar/* 66655682Smarkm * Call `func' for each log record in the log in `context' 66755682Smarkm */ 66855682Smarkm 66955682Smarkmkadm5_ret_t 67055682Smarkmkadm5_log_foreach (kadm5_server_context *context, 67155682Smarkm void (*func)(kadm5_server_context *server_context, 67255682Smarkm u_int32_t ver, 67355682Smarkm time_t timestamp, 67455682Smarkm enum kadm_ops op, 67555682Smarkm u_int32_t len, 67655682Smarkm krb5_storage *sp)) 67755682Smarkm{ 67855682Smarkm int fd = context->log_context.log_fd; 67955682Smarkm krb5_storage *sp; 68055682Smarkm 68155682Smarkm lseek (fd, 0, SEEK_SET); 68255682Smarkm sp = krb5_storage_from_fd (fd); 68355682Smarkm for (;;) { 68455682Smarkm int32_t ver, timestamp, op, len; 68555682Smarkm 68655682Smarkm if(krb5_ret_int32 (sp, &ver) != 0) 68755682Smarkm break; 68855682Smarkm krb5_ret_int32 (sp, ×tamp); 68955682Smarkm krb5_ret_int32 (sp, &op); 69055682Smarkm krb5_ret_int32 (sp, &len); 69155682Smarkm (*func)(context, ver, timestamp, op, len, sp); 69255682Smarkm sp->seek(sp, 8, SEEK_CUR); 69355682Smarkm } 69455682Smarkm return 0; 69555682Smarkm} 69655682Smarkm 69755682Smarkm/* 69855682Smarkm * Go to end of log. 69955682Smarkm */ 70055682Smarkm 70155682Smarkmkrb5_storage * 70255682Smarkmkadm5_log_goto_end (int fd) 70355682Smarkm{ 70455682Smarkm krb5_storage *sp; 70555682Smarkm 70655682Smarkm sp = krb5_storage_from_fd (fd); 70755682Smarkm sp->seek(sp, 0, SEEK_END); 70855682Smarkm return sp; 70955682Smarkm} 71055682Smarkm 71155682Smarkm/* 71255682Smarkm * Return previous log entry. 71355682Smarkm */ 71455682Smarkm 71555682Smarkmkadm5_ret_t 71655682Smarkmkadm5_log_previous (krb5_storage *sp, 71755682Smarkm u_int32_t *ver, 71855682Smarkm time_t *timestamp, 71955682Smarkm enum kadm_ops *op, 72055682Smarkm u_int32_t *len) 72155682Smarkm{ 72255682Smarkm off_t off; 72355682Smarkm int32_t tmp; 72455682Smarkm 72555682Smarkm sp->seek(sp, -8, SEEK_CUR); 72655682Smarkm krb5_ret_int32 (sp, &tmp); 72755682Smarkm *len = tmp; 72855682Smarkm krb5_ret_int32 (sp, &tmp); 72955682Smarkm *ver = tmp; 73055682Smarkm off = 24 + *len; 73155682Smarkm sp->seek(sp, -off, SEEK_CUR); 73255682Smarkm krb5_ret_int32 (sp, &tmp); 73355682Smarkm assert(tmp == *ver); 73455682Smarkm krb5_ret_int32 (sp, &tmp); 73555682Smarkm *timestamp = tmp; 73655682Smarkm krb5_ret_int32 (sp, &tmp); 73755682Smarkm *op = tmp; 73855682Smarkm krb5_ret_int32 (sp, &tmp); 73955682Smarkm assert(tmp == *len); 74055682Smarkm return 0; 74155682Smarkm} 74255682Smarkm 74355682Smarkm/* 74455682Smarkm * Replay a record from the log 74555682Smarkm */ 74655682Smarkm 74755682Smarkmkadm5_ret_t 74855682Smarkmkadm5_log_replay (kadm5_server_context *context, 74955682Smarkm enum kadm_ops op, 75055682Smarkm u_int32_t ver, 75155682Smarkm u_int32_t len, 75255682Smarkm krb5_storage *sp) 75355682Smarkm{ 75455682Smarkm switch (op) { 75555682Smarkm case kadm_create : 75655682Smarkm return kadm5_log_replay_create (context, ver, len, sp); 75755682Smarkm case kadm_delete : 75855682Smarkm return kadm5_log_replay_delete (context, ver, len, sp); 75955682Smarkm case kadm_rename : 76055682Smarkm return kadm5_log_replay_rename (context, ver, len, sp); 76155682Smarkm case kadm_modify : 76255682Smarkm return kadm5_log_replay_modify (context, ver, len, sp); 76372445Sassar case kadm_nop : 76472445Sassar return kadm5_log_replay_nop (context, ver, len, sp); 76555682Smarkm default : 76655682Smarkm return KADM5_FAILURE; 76755682Smarkm } 76855682Smarkm} 76972445Sassar 77072445Sassar/* 77172445Sassar * truncate the log - i.e. create an empty file with just (nop vno + 2) 77272445Sassar */ 77372445Sassar 77472445Sassarkadm5_ret_t 77572445Sassarkadm5_log_truncate (kadm5_server_context *server_context) 77672445Sassar{ 77772445Sassar kadm5_ret_t ret; 77872445Sassar u_int32_t vno; 77972445Sassar 78072445Sassar ret = kadm5_log_init (server_context); 78172445Sassar if (ret) 78272445Sassar return ret; 78372445Sassar 78472445Sassar ret = kadm5_log_get_version (server_context, &vno); 78572445Sassar if (ret) 78672445Sassar return ret; 78772445Sassar 78872445Sassar ret = kadm5_log_reinit (server_context); 78972445Sassar if (ret) 79072445Sassar return ret; 79172445Sassar 79272445Sassar ret = kadm5_log_set_version (server_context, vno + 1); 79372445Sassar if (ret) 79472445Sassar return ret; 79572445Sassar 79672445Sassar ret = kadm5_log_nop (server_context); 79772445Sassar if (ret) 79872445Sassar return ret; 79972445Sassar 80072445Sassar ret = kadm5_log_end (server_context); 80172445Sassar if (ret) 80272445Sassar return ret; 80372445Sassar return 0; 80472445Sassar 80572445Sassar} 806