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