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, &timestamp);
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