1b528cefcSMark Murray /*
2c19800e8SDoug Rabson * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "kadm5_locl.h"
35c19800e8SDoug Rabson #include "heim_threads.h"
36b528cefcSMark Murray
37c19800e8SDoug Rabson RCSID("$Id$");
38b528cefcSMark Murray
39b528cefcSMark Murray /*
40b528cefcSMark Murray * A log record consists of:
41b528cefcSMark Murray *
42b528cefcSMark Murray * version number 4 bytes
43b528cefcSMark Murray * time in seconds 4 bytes
44b528cefcSMark Murray * operation (enum kadm_ops) 4 bytes
45b528cefcSMark Murray * length of record 4 bytes
46b528cefcSMark Murray * data... n bytes
47b528cefcSMark Murray * length of record 4 bytes
48b528cefcSMark Murray * version number 4 bytes
49b528cefcSMark Murray *
50b528cefcSMark Murray */
51b528cefcSMark Murray
52b528cefcSMark Murray kadm5_ret_t
kadm5_log_get_version_fd(int fd,uint32_t * ver)535e9cd1aeSAssar Westerlund kadm5_log_get_version_fd (int fd,
54c19800e8SDoug Rabson uint32_t *ver)
55b528cefcSMark Murray {
56b528cefcSMark Murray int ret;
57b528cefcSMark Murray krb5_storage *sp;
58b528cefcSMark Murray int32_t old_version;
59b528cefcSMark Murray
60b528cefcSMark Murray ret = lseek (fd, 0, SEEK_END);
61b528cefcSMark Murray if(ret < 0)
62b528cefcSMark Murray return errno;
63b528cefcSMark Murray if(ret == 0) {
64b528cefcSMark Murray *ver = 0;
65b528cefcSMark Murray return 0;
66b528cefcSMark Murray }
67b528cefcSMark Murray sp = krb5_storage_from_fd (fd);
688373020dSJacques Vidrine krb5_storage_seek(sp, -4, SEEK_CUR);
69b528cefcSMark Murray krb5_ret_int32 (sp, &old_version);
70b528cefcSMark Murray *ver = old_version;
71b528cefcSMark Murray krb5_storage_free(sp);
72b528cefcSMark Murray lseek (fd, 0, SEEK_END);
73b528cefcSMark Murray return 0;
74b528cefcSMark Murray }
75b528cefcSMark Murray
76b528cefcSMark Murray kadm5_ret_t
kadm5_log_get_version(kadm5_server_context * context,uint32_t * ver)77c19800e8SDoug Rabson kadm5_log_get_version (kadm5_server_context *context, uint32_t *ver)
785e9cd1aeSAssar Westerlund {
795e9cd1aeSAssar Westerlund return kadm5_log_get_version_fd (context->log_context.log_fd, ver);
805e9cd1aeSAssar Westerlund }
815e9cd1aeSAssar Westerlund
825e9cd1aeSAssar Westerlund kadm5_ret_t
kadm5_log_set_version(kadm5_server_context * context,uint32_t vno)83c19800e8SDoug Rabson kadm5_log_set_version (kadm5_server_context *context, uint32_t vno)
845e9cd1aeSAssar Westerlund {
855e9cd1aeSAssar Westerlund kadm5_log_context *log_context = &context->log_context;
865e9cd1aeSAssar Westerlund
875e9cd1aeSAssar Westerlund log_context->version = vno;
885e9cd1aeSAssar Westerlund return 0;
895e9cd1aeSAssar Westerlund }
905e9cd1aeSAssar Westerlund
915e9cd1aeSAssar Westerlund kadm5_ret_t
kadm5_log_init(kadm5_server_context * context)92b528cefcSMark Murray kadm5_log_init (kadm5_server_context *context)
93b528cefcSMark Murray {
94b528cefcSMark Murray int fd;
95b528cefcSMark Murray kadm5_ret_t ret;
96b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context;
97b528cefcSMark Murray
98b528cefcSMark Murray if (log_context->log_fd != -1)
99b528cefcSMark Murray return 0;
100b528cefcSMark Murray fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600);
101c19800e8SDoug Rabson if (fd < 0) {
102c19800e8SDoug Rabson ret = errno;
103c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "kadm5_log_init: open %s",
104b528cefcSMark Murray log_context->log_file);
105c19800e8SDoug Rabson return ret;
106b528cefcSMark Murray }
107c19800e8SDoug Rabson if (flock (fd, LOCK_EX) < 0) {
108c19800e8SDoug Rabson ret = errno;
109b528cefcSMark Murray krb5_set_error_message(context->context, ret, "kadm5_log_init: flock %s",
110b528cefcSMark Murray log_context->log_file);
111b528cefcSMark Murray close (fd);
112b528cefcSMark Murray return errno;
1135e9cd1aeSAssar Westerlund }
114b528cefcSMark Murray
115b528cefcSMark Murray ret = kadm5_log_get_version_fd (fd, &log_context->version);
116b528cefcSMark Murray if (ret)
117b528cefcSMark Murray return ret;
118b528cefcSMark Murray
119b528cefcSMark Murray log_context->log_fd = fd;
120b528cefcSMark Murray return 0;
121b528cefcSMark Murray }
1225e9cd1aeSAssar Westerlund
1235e9cd1aeSAssar Westerlund kadm5_ret_t
kadm5_log_reinit(kadm5_server_context * context)1245e9cd1aeSAssar Westerlund kadm5_log_reinit (kadm5_server_context *context)
1255e9cd1aeSAssar Westerlund {
1265e9cd1aeSAssar Westerlund int fd;
1275e9cd1aeSAssar Westerlund kadm5_log_context *log_context = &context->log_context;
128c19800e8SDoug Rabson
1295e9cd1aeSAssar Westerlund if (log_context->log_fd != -1) {
1305e9cd1aeSAssar Westerlund flock (log_context->log_fd, LOCK_UN);
1315e9cd1aeSAssar Westerlund close (log_context->log_fd);
1325e9cd1aeSAssar Westerlund log_context->log_fd = -1;
1335e9cd1aeSAssar Westerlund }
1345e9cd1aeSAssar Westerlund fd = open (log_context->log_file, O_RDWR | O_CREAT | O_TRUNC, 0600);
1355e9cd1aeSAssar Westerlund if (fd < 0)
1365e9cd1aeSAssar Westerlund return errno;
1375e9cd1aeSAssar Westerlund if (flock (fd, LOCK_EX) < 0) {
1385e9cd1aeSAssar Westerlund close (fd);
1395e9cd1aeSAssar Westerlund return errno;
1405e9cd1aeSAssar Westerlund }
1415e9cd1aeSAssar Westerlund
1425e9cd1aeSAssar Westerlund log_context->version = 0;
1435e9cd1aeSAssar Westerlund log_context->log_fd = fd;
1445e9cd1aeSAssar Westerlund return 0;
1455e9cd1aeSAssar Westerlund }
1465e9cd1aeSAssar Westerlund
147b528cefcSMark Murray
148b528cefcSMark Murray kadm5_ret_t
kadm5_log_end(kadm5_server_context * context)149b528cefcSMark Murray kadm5_log_end (kadm5_server_context *context)
150b528cefcSMark Murray {
151b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context;
152b528cefcSMark Murray int fd = log_context->log_fd;
153b528cefcSMark Murray
154b528cefcSMark Murray flock (fd, LOCK_UN);
155b528cefcSMark Murray close(fd);
156b528cefcSMark Murray log_context->log_fd = -1;
157b528cefcSMark Murray return 0;
158b528cefcSMark Murray }
159b528cefcSMark Murray
160b528cefcSMark Murray static kadm5_ret_t
kadm5_log_preamble(kadm5_server_context * context,krb5_storage * sp,enum kadm_ops op)161b528cefcSMark Murray kadm5_log_preamble (kadm5_server_context *context,
162b528cefcSMark Murray krb5_storage *sp,
163b528cefcSMark Murray enum kadm_ops op)
164b528cefcSMark Murray {
165b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context;
166b528cefcSMark Murray kadm5_ret_t kadm_ret;
167b528cefcSMark Murray
168b528cefcSMark Murray kadm_ret = kadm5_log_init (context);
169b528cefcSMark Murray if (kadm_ret)
170b528cefcSMark Murray return kadm_ret;
171b528cefcSMark Murray
172b528cefcSMark Murray krb5_store_int32 (sp, ++log_context->version);
173b528cefcSMark Murray krb5_store_int32 (sp, time(NULL));
174b528cefcSMark Murray krb5_store_int32 (sp, op);
175b528cefcSMark Murray return 0;
176b528cefcSMark Murray }
177b528cefcSMark Murray
178b528cefcSMark Murray static kadm5_ret_t
kadm5_log_postamble(kadm5_log_context * context,krb5_storage * sp)179b528cefcSMark Murray kadm5_log_postamble (kadm5_log_context *context,
180b528cefcSMark Murray krb5_storage *sp)
181b528cefcSMark Murray {
182b528cefcSMark Murray krb5_store_int32 (sp, context->version);
183b528cefcSMark Murray return 0;
184b528cefcSMark Murray }
185b528cefcSMark Murray
186b528cefcSMark Murray /*
187b528cefcSMark Murray * flush the log record in `sp'.
188b528cefcSMark Murray */
189b528cefcSMark Murray
190b528cefcSMark Murray static kadm5_ret_t
kadm5_log_flush(kadm5_log_context * log_context,krb5_storage * sp)191b528cefcSMark Murray kadm5_log_flush (kadm5_log_context *log_context,
192b528cefcSMark Murray krb5_storage *sp)
193b528cefcSMark Murray {
194b528cefcSMark Murray krb5_data data;
195b528cefcSMark Murray size_t len;
196b528cefcSMark Murray ssize_t ret;
197b528cefcSMark Murray
198b528cefcSMark Murray krb5_storage_to_data(sp, &data);
199b528cefcSMark Murray len = data.length;
200b528cefcSMark Murray ret = write (log_context->log_fd, data.data, len);
201b528cefcSMark Murray if (ret < 0 || (size_t)ret != len) {
202b528cefcSMark Murray krb5_data_free(&data);
203b528cefcSMark Murray return errno;
204b528cefcSMark Murray }
205b528cefcSMark Murray if (fsync (log_context->log_fd) < 0) {
206b528cefcSMark Murray krb5_data_free(&data);
207b528cefcSMark Murray return errno;
208b528cefcSMark Murray }
209b528cefcSMark Murray
210b528cefcSMark Murray /*
211b528cefcSMark Murray * Try to send a signal to any running `ipropd-master'
212b528cefcSMark Murray */
213b528cefcSMark Murray #ifndef NO_UNIX_SOCKETS
214b528cefcSMark Murray sendto (log_context->socket_fd,
215b528cefcSMark Murray (void *)&log_context->version,
216b528cefcSMark Murray sizeof(log_context->version),
217b528cefcSMark Murray 0,
218b528cefcSMark Murray (struct sockaddr *)&log_context->socket_name,
219b528cefcSMark Murray sizeof(log_context->socket_name));
220b528cefcSMark Murray #else
221b528cefcSMark Murray sendto (log_context->socket_fd,
222b528cefcSMark Murray (void *)&log_context->version,
223b528cefcSMark Murray sizeof(log_context->version),
224b528cefcSMark Murray 0,
225b528cefcSMark Murray log_context->socket_info->ai_addr,
226b528cefcSMark Murray log_context->socket_info->ai_addrlen);
227b528cefcSMark Murray #endif
228b528cefcSMark Murray
229b528cefcSMark Murray krb5_data_free(&data);
230b528cefcSMark Murray return 0;
231b528cefcSMark Murray }
232b528cefcSMark Murray
233b528cefcSMark Murray /*
234b528cefcSMark Murray * Add a `create' operation to the log.
235b528cefcSMark Murray */
236b528cefcSMark Murray
237b528cefcSMark Murray kadm5_ret_t
kadm5_log_create(kadm5_server_context * context,hdb_entry * ent)238b528cefcSMark Murray kadm5_log_create (kadm5_server_context *context,
239b528cefcSMark Murray hdb_entry *ent)
240b528cefcSMark Murray {
241b528cefcSMark Murray krb5_storage *sp;
242b528cefcSMark Murray kadm5_ret_t ret;
243b528cefcSMark Murray krb5_data value;
244b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context;
245b528cefcSMark Murray
246b528cefcSMark Murray sp = krb5_storage_emem();
2478373020dSJacques Vidrine ret = hdb_entry2value (context->context, ent, &value);
248b528cefcSMark Murray if (ret) {
249b528cefcSMark Murray krb5_storage_free(sp);
250b528cefcSMark Murray return ret;
251b528cefcSMark Murray }
252b528cefcSMark Murray ret = kadm5_log_preamble (context, sp, kadm_create);
253b528cefcSMark Murray if (ret) {
254b528cefcSMark Murray krb5_data_free (&value);
255b528cefcSMark Murray krb5_storage_free(sp);
256b528cefcSMark Murray return ret;
257b528cefcSMark Murray }
258b528cefcSMark Murray krb5_store_int32 (sp, value.length);
259b528cefcSMark Murray krb5_storage_write(sp, value.data, value.length);
260b528cefcSMark Murray krb5_store_int32 (sp, value.length);
261b528cefcSMark Murray krb5_data_free (&value);
262b528cefcSMark Murray ret = kadm5_log_postamble (log_context, sp);
263b528cefcSMark Murray if (ret) {
264b528cefcSMark Murray krb5_storage_free (sp);
265b528cefcSMark Murray return ret;
266b528cefcSMark Murray }
267b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp);
268c19800e8SDoug Rabson krb5_storage_free (sp);
269b528cefcSMark Murray if (ret)
270c19800e8SDoug Rabson return ret;
271c19800e8SDoug Rabson ret = kadm5_log_end (context);
272b528cefcSMark Murray return ret;
273b528cefcSMark Murray }
274b528cefcSMark Murray
275b528cefcSMark Murray /*
276c19800e8SDoug Rabson * Read the data of a create log record from `sp' and change the
277c19800e8SDoug Rabson * database.
278c19800e8SDoug Rabson */
279b528cefcSMark Murray
280bbd80c28SJacques Vidrine static kadm5_ret_t
kadm5_log_replay_create(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)281c19800e8SDoug Rabson kadm5_log_replay_create (kadm5_server_context *context,
282c19800e8SDoug Rabson uint32_t ver,
283bbd80c28SJacques Vidrine uint32_t len,
284c19800e8SDoug Rabson krb5_storage *sp)
2858373020dSJacques Vidrine {
286c19800e8SDoug Rabson krb5_error_code ret;
287b528cefcSMark Murray krb5_data data;
288c19800e8SDoug Rabson hdb_entry_ex ent;
289c19800e8SDoug Rabson
290c19800e8SDoug Rabson memset(&ent, 0, sizeof(ent));
291b528cefcSMark Murray
292c19800e8SDoug Rabson ret = krb5_data_alloc (&data, len);
293c19800e8SDoug Rabson if (ret) {
294b528cefcSMark Murray krb5_set_error_message(context->context, ret, "out of memory");
295b528cefcSMark Murray return ret;
296b528cefcSMark Murray }
297b528cefcSMark Murray krb5_storage_read (sp, data.data, len);
298b528cefcSMark Murray ret = hdb_value2entry (context->context, &data, &ent.entry);
299b528cefcSMark Murray krb5_data_free(&data);
300b528cefcSMark Murray if (ret) {
301b528cefcSMark Murray krb5_set_error_message(context->context, ret,
302b528cefcSMark Murray "Unmarshaling hdb entry failed");
303b528cefcSMark Murray return ret;
304b528cefcSMark Murray }
305b528cefcSMark Murray ret = context->db->hdb_store(context->context, context->db, 0, &ent);
306b528cefcSMark Murray hdb_free_entry (context->context, &ent);
307b528cefcSMark Murray return ret;
308b528cefcSMark Murray }
309b528cefcSMark Murray
310b528cefcSMark Murray /*
311b528cefcSMark Murray * Add a `delete' operation to the log.
312b528cefcSMark Murray */
313c19800e8SDoug Rabson
314c19800e8SDoug Rabson kadm5_ret_t
kadm5_log_delete(kadm5_server_context * context,krb5_principal princ)315b528cefcSMark Murray kadm5_log_delete (kadm5_server_context *context,
316c19800e8SDoug Rabson krb5_principal princ)
317c19800e8SDoug Rabson {
318c19800e8SDoug Rabson krb5_storage *sp;
319c19800e8SDoug Rabson kadm5_ret_t ret;
320c19800e8SDoug Rabson off_t off;
3218373020dSJacques Vidrine off_t len;
322c19800e8SDoug Rabson kadm5_log_context *log_context = &context->log_context;
323c19800e8SDoug Rabson
324c19800e8SDoug Rabson sp = krb5_storage_emem();
3258373020dSJacques Vidrine if (sp == NULL)
3268373020dSJacques Vidrine return ENOMEM;
327c19800e8SDoug Rabson ret = kadm5_log_preamble (context, sp, kadm_delete);
328b528cefcSMark Murray if (ret)
329c19800e8SDoug Rabson goto out;
330c19800e8SDoug Rabson ret = krb5_store_int32 (sp, 0);
331c19800e8SDoug Rabson if (ret)
332c19800e8SDoug Rabson goto out;
333c19800e8SDoug Rabson off = krb5_storage_seek (sp, 0, SEEK_CUR);
334c19800e8SDoug Rabson ret = krb5_store_principal (sp, princ);
335c19800e8SDoug Rabson if (ret)
336c19800e8SDoug Rabson goto out;
337c19800e8SDoug Rabson len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
338c19800e8SDoug Rabson krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
339c19800e8SDoug Rabson ret = krb5_store_int32 (sp, len);
340b528cefcSMark Murray if (ret)
341c19800e8SDoug Rabson goto out;
342c19800e8SDoug Rabson krb5_storage_seek(sp, len, SEEK_CUR);
343b528cefcSMark Murray ret = krb5_store_int32 (sp, len);
344b528cefcSMark Murray if (ret)
345b528cefcSMark Murray goto out;
346b528cefcSMark Murray ret = kadm5_log_postamble (log_context, sp);
347b528cefcSMark Murray if (ret)
348b528cefcSMark Murray goto out;
349b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp);
350c19800e8SDoug Rabson if (ret)
351b528cefcSMark Murray goto out;
352c19800e8SDoug Rabson ret = kadm5_log_end (context);
353c19800e8SDoug Rabson out:
354b528cefcSMark Murray krb5_storage_free (sp);
355b528cefcSMark Murray return ret;
356b528cefcSMark Murray }
357c19800e8SDoug Rabson
358b528cefcSMark Murray /*
359c19800e8SDoug Rabson * Read a `delete' log operation from `sp' and apply it.
360c19800e8SDoug Rabson */
361c19800e8SDoug Rabson
362c19800e8SDoug Rabson static kadm5_ret_t
kadm5_log_replay_delete(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)363c19800e8SDoug Rabson kadm5_log_replay_delete (kadm5_server_context *context,
364c19800e8SDoug Rabson uint32_t ver,
365b528cefcSMark Murray uint32_t len,
366c19800e8SDoug Rabson krb5_storage *sp)
367c19800e8SDoug Rabson {
368b528cefcSMark Murray krb5_error_code ret;
369b528cefcSMark Murray krb5_principal principal;
370b528cefcSMark Murray
371b528cefcSMark Murray ret = krb5_ret_principal (sp, &principal);
372b528cefcSMark Murray if (ret) {
373b528cefcSMark Murray krb5_set_error_message(context->context, ret, "Failed to read deleted "
374b528cefcSMark Murray "principal from log version: %ld", (long)ver);
375b528cefcSMark Murray return ret;
376b528cefcSMark Murray }
377b528cefcSMark Murray
378b528cefcSMark Murray ret = context->db->hdb_remove(context->context, context->db, principal);
379b528cefcSMark Murray krb5_free_principal (context->context, principal);
380b528cefcSMark Murray return ret;
381b528cefcSMark Murray }
382b528cefcSMark Murray
383b528cefcSMark Murray /*
384b528cefcSMark Murray * Add a `rename' operation to the log.
385b528cefcSMark Murray */
386b528cefcSMark Murray
387c19800e8SDoug Rabson kadm5_ret_t
kadm5_log_rename(kadm5_server_context * context,krb5_principal source,hdb_entry * ent)388c19800e8SDoug Rabson kadm5_log_rename (kadm5_server_context *context,
389b528cefcSMark Murray krb5_principal source,
390b528cefcSMark Murray hdb_entry *ent)
391c19800e8SDoug Rabson {
392c19800e8SDoug Rabson krb5_storage *sp;
393c19800e8SDoug Rabson kadm5_ret_t ret;
394b528cefcSMark Murray off_t off;
395c19800e8SDoug Rabson off_t len;
396c19800e8SDoug Rabson krb5_data value;
397c19800e8SDoug Rabson kadm5_log_context *log_context = &context->log_context;
398c19800e8SDoug Rabson
399c19800e8SDoug Rabson krb5_data_zero(&value);
400c19800e8SDoug Rabson
4018373020dSJacques Vidrine sp = krb5_storage_emem();
402c19800e8SDoug Rabson ret = hdb_entry2value (context->context, ent, &value);
403c19800e8SDoug Rabson if (ret)
404c19800e8SDoug Rabson goto failed;
405c19800e8SDoug Rabson
4068373020dSJacques Vidrine ret = kadm5_log_preamble (context, sp, kadm_rename);
4078373020dSJacques Vidrine if (ret)
408b528cefcSMark Murray goto failed;
4098373020dSJacques Vidrine
410c19800e8SDoug Rabson ret = krb5_store_int32 (sp, 0);
411b528cefcSMark Murray if (ret)
412c19800e8SDoug Rabson goto failed;
413c19800e8SDoug Rabson off = krb5_storage_seek (sp, 0, SEEK_CUR);
414c19800e8SDoug Rabson ret = krb5_store_principal (sp, source);
415c19800e8SDoug Rabson if (ret)
416c19800e8SDoug Rabson goto failed;
417c19800e8SDoug Rabson
418c19800e8SDoug Rabson krb5_storage_write(sp, value.data, value.length);
419c19800e8SDoug Rabson len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
420c19800e8SDoug Rabson
421c19800e8SDoug Rabson krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
422c19800e8SDoug Rabson ret = krb5_store_int32 (sp, len);
423c19800e8SDoug Rabson if (ret)
424c19800e8SDoug Rabson goto failed;
425c19800e8SDoug Rabson
426c19800e8SDoug Rabson krb5_storage_seek(sp, len, SEEK_CUR);
427c19800e8SDoug Rabson ret = krb5_store_int32 (sp, len);
428c19800e8SDoug Rabson if (ret)
429c19800e8SDoug Rabson goto failed;
430c19800e8SDoug Rabson
431c19800e8SDoug Rabson ret = kadm5_log_postamble (log_context, sp);
432c19800e8SDoug Rabson if (ret)
433c19800e8SDoug Rabson goto failed;
434b528cefcSMark Murray
435b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp);
436b528cefcSMark Murray if (ret)
437b528cefcSMark Murray goto failed;
438b528cefcSMark Murray krb5_storage_free (sp);
439b528cefcSMark Murray krb5_data_free (&value);
440b528cefcSMark Murray
441c19800e8SDoug Rabson return kadm5_log_end (context);
442b528cefcSMark Murray
443c19800e8SDoug Rabson failed:
444c19800e8SDoug Rabson krb5_data_free(&value);
445b528cefcSMark Murray krb5_storage_free(sp);
446b528cefcSMark Murray return ret;
447b528cefcSMark Murray }
448b528cefcSMark Murray
449c19800e8SDoug Rabson /*
450b528cefcSMark Murray * Read a `rename' log operation from `sp' and apply it.
451b528cefcSMark Murray */
452b528cefcSMark Murray
453b528cefcSMark Murray static kadm5_ret_t
kadm5_log_replay_rename(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)454c19800e8SDoug Rabson kadm5_log_replay_rename (kadm5_server_context *context,
455c19800e8SDoug Rabson uint32_t ver,
4568373020dSJacques Vidrine uint32_t len,
457c19800e8SDoug Rabson krb5_storage *sp)
458c19800e8SDoug Rabson {
459c19800e8SDoug Rabson krb5_error_code ret;
460c19800e8SDoug Rabson krb5_principal source;
461c19800e8SDoug Rabson hdb_entry_ex target_ent;
462c19800e8SDoug Rabson krb5_data value;
4638373020dSJacques Vidrine off_t off;
464b528cefcSMark Murray size_t princ_len, data_len;
465bbd80c28SJacques Vidrine
466bbd80c28SJacques Vidrine memset(&target_ent, 0, sizeof(target_ent));
467bbd80c28SJacques Vidrine
468bbd80c28SJacques Vidrine off = krb5_storage_seek(sp, 0, SEEK_CUR);
469bbd80c28SJacques Vidrine ret = krb5_ret_principal (sp, &source);
4708373020dSJacques Vidrine if (ret) {
471c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "Failed to read renamed "
472b528cefcSMark Murray "principal in log, version: %ld", (long)ver);
473b528cefcSMark Murray return ret;
474b528cefcSMark Murray }
475b528cefcSMark Murray princ_len = krb5_storage_seek(sp, 0, SEEK_CUR) - off;
476b528cefcSMark Murray data_len = len - princ_len;
477c19800e8SDoug Rabson ret = krb5_data_alloc (&value, data_len);
478c19800e8SDoug Rabson if (ret) {
479b528cefcSMark Murray krb5_free_principal (context->context, source);
480b528cefcSMark Murray return ret;
481b528cefcSMark Murray }
482b528cefcSMark Murray krb5_storage_read (sp, value.data, data_len);
483b528cefcSMark Murray ret = hdb_value2entry (context->context, &value, &target_ent.entry);
484c19800e8SDoug Rabson krb5_data_free(&value);
485b528cefcSMark Murray if (ret) {
486b528cefcSMark Murray krb5_free_principal (context->context, source);
487b528cefcSMark Murray return ret;
488b528cefcSMark Murray }
489b528cefcSMark Murray ret = context->db->hdb_store (context->context, context->db,
490b528cefcSMark Murray 0, &target_ent);
491b528cefcSMark Murray hdb_free_entry (context->context, &target_ent);
492b528cefcSMark Murray if (ret) {
493b528cefcSMark Murray krb5_free_principal (context->context, source);
494b528cefcSMark Murray return ret;
495b528cefcSMark Murray }
496b528cefcSMark Murray ret = context->db->hdb_remove (context->context, context->db, source);
497c19800e8SDoug Rabson krb5_free_principal (context->context, source);
498b528cefcSMark Murray return ret;
499b528cefcSMark Murray }
500b528cefcSMark Murray
501b528cefcSMark Murray
502c19800e8SDoug Rabson /*
503b528cefcSMark Murray * Add a `modify' operation to the log.
504b528cefcSMark Murray */
505c19800e8SDoug Rabson
506c19800e8SDoug Rabson kadm5_ret_t
kadm5_log_modify(kadm5_server_context * context,hdb_entry * ent,uint32_t mask)507b528cefcSMark Murray kadm5_log_modify (kadm5_server_context *context,
508b528cefcSMark Murray hdb_entry *ent,
509b528cefcSMark Murray uint32_t mask)
510c19800e8SDoug Rabson {
511c19800e8SDoug Rabson krb5_storage *sp;
512c19800e8SDoug Rabson kadm5_ret_t ret;
513c19800e8SDoug Rabson krb5_data value;
514c19800e8SDoug Rabson uint32_t len;
515c19800e8SDoug Rabson kadm5_log_context *log_context = &context->log_context;
516c19800e8SDoug Rabson
517c19800e8SDoug Rabson krb5_data_zero(&value);
518c19800e8SDoug Rabson
519c19800e8SDoug Rabson sp = krb5_storage_emem();
520c19800e8SDoug Rabson ret = hdb_entry2value (context->context, ent, &value);
521c19800e8SDoug Rabson if (ret)
522c19800e8SDoug Rabson goto failed;
523c19800e8SDoug Rabson
524c19800e8SDoug Rabson ret = kadm5_log_preamble (context, sp, kadm_modify);
525c19800e8SDoug Rabson if (ret)
526c19800e8SDoug Rabson goto failed;
527c19800e8SDoug Rabson
528c19800e8SDoug Rabson len = value.length + 4;
529c19800e8SDoug Rabson ret = krb5_store_int32 (sp, len);
530c19800e8SDoug Rabson if (ret)
531c19800e8SDoug Rabson goto failed;
532c19800e8SDoug Rabson ret = krb5_store_int32 (sp, mask);
533c19800e8SDoug Rabson if (ret)
534c19800e8SDoug Rabson goto failed;
535c19800e8SDoug Rabson krb5_storage_write (sp, value.data, value.length);
536c19800e8SDoug Rabson
537c19800e8SDoug Rabson ret = krb5_store_int32 (sp, len);
538c19800e8SDoug Rabson if (ret)
539c19800e8SDoug Rabson goto failed;
540b528cefcSMark Murray ret = kadm5_log_postamble (log_context, sp);
541b528cefcSMark Murray if (ret)
542b528cefcSMark Murray goto failed;
543b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp);
544b528cefcSMark Murray if (ret)
545b528cefcSMark Murray goto failed;
546b528cefcSMark Murray krb5_data_free(&value);
547c19800e8SDoug Rabson krb5_storage_free (sp);
548b528cefcSMark Murray return kadm5_log_end (context);
549c19800e8SDoug Rabson failed:
550c19800e8SDoug Rabson krb5_data_free(&value);
551b528cefcSMark Murray krb5_storage_free(sp);
552b528cefcSMark Murray return ret;
553b528cefcSMark Murray }
554b528cefcSMark Murray
555b528cefcSMark Murray /*
556c19800e8SDoug Rabson * Read a `modify' log operation from `sp' and apply it.
557c19800e8SDoug Rabson */
558c19800e8SDoug Rabson
559b528cefcSMark Murray static kadm5_ret_t
kadm5_log_replay_modify(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)560b528cefcSMark Murray kadm5_log_replay_modify (kadm5_server_context *context,
561b528cefcSMark Murray uint32_t ver,
562bbd80c28SJacques Vidrine uint32_t len,
563c19800e8SDoug Rabson krb5_storage *sp)
564c19800e8SDoug Rabson {
565bbd80c28SJacques Vidrine krb5_error_code ret;
566c19800e8SDoug Rabson int32_t mask;
5678373020dSJacques Vidrine krb5_data value;
568c19800e8SDoug Rabson hdb_entry_ex ent, log_ent;
569b528cefcSMark Murray
570b528cefcSMark Murray memset(&log_ent, 0, sizeof(log_ent));
571b528cefcSMark Murray
572c19800e8SDoug Rabson krb5_ret_int32 (sp, &mask);
573c19800e8SDoug Rabson len -= 4;
574c19800e8SDoug Rabson ret = krb5_data_alloc (&value, len);
575c19800e8SDoug Rabson if (ret) {
576c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "out of memory");
577b528cefcSMark Murray return ret;
578c19800e8SDoug Rabson }
579b528cefcSMark Murray krb5_storage_read (sp, value.data, len);
580c19800e8SDoug Rabson ret = hdb_value2entry (context->context, &value, &log_ent.entry);
581c19800e8SDoug Rabson krb5_data_free(&value);
5825e9cd1aeSAssar Westerlund if (ret)
583c19800e8SDoug Rabson return ret;
584c19800e8SDoug Rabson
585c19800e8SDoug Rabson memset(&ent, 0, sizeof(ent));
586c19800e8SDoug Rabson ret = context->db->hdb_fetch_kvno(context->context, context->db,
587c19800e8SDoug Rabson log_ent.entry.principal,
588c19800e8SDoug Rabson HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
589c19800e8SDoug Rabson if (ret)
590c19800e8SDoug Rabson goto out;
591c19800e8SDoug Rabson if (mask & KADM5_PRINC_EXPIRE_TIME) {
592b528cefcSMark Murray if (log_ent.entry.valid_end == NULL) {
5935e9cd1aeSAssar Westerlund ent.entry.valid_end = NULL;
594b528cefcSMark Murray } else {
595c19800e8SDoug Rabson if (ent.entry.valid_end == NULL) {
596c19800e8SDoug Rabson ent.entry.valid_end = malloc(sizeof(*ent.entry.valid_end));
5975e9cd1aeSAssar Westerlund if (ent.entry.valid_end == NULL) {
598c19800e8SDoug Rabson ret = ENOMEM;
599c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "out of memory");
600c19800e8SDoug Rabson goto out;
601c19800e8SDoug Rabson }
602c19800e8SDoug Rabson }
603c19800e8SDoug Rabson *ent.entry.valid_end = *log_ent.entry.valid_end;
604c19800e8SDoug Rabson }
605c19800e8SDoug Rabson }
606c19800e8SDoug Rabson if (mask & KADM5_PW_EXPIRATION) {
607b528cefcSMark Murray if (log_ent.entry.pw_end == NULL) {
6085e9cd1aeSAssar Westerlund ent.entry.pw_end = NULL;
609b528cefcSMark Murray } else {
610b528cefcSMark Murray if (ent.entry.pw_end == NULL) {
611b528cefcSMark Murray ent.entry.pw_end = malloc(sizeof(*ent.entry.pw_end));
612b528cefcSMark Murray if (ent.entry.pw_end == NULL) {
613c19800e8SDoug Rabson ret = ENOMEM;
614b528cefcSMark Murray krb5_set_error_message(context->context, ret, "out of memory");
615b528cefcSMark Murray goto out;
616c19800e8SDoug Rabson }
617c19800e8SDoug Rabson }
6185e9cd1aeSAssar Westerlund *ent.entry.pw_end = *log_ent.entry.pw_end;
619c19800e8SDoug Rabson }
620c19800e8SDoug Rabson }
621c19800e8SDoug Rabson if (mask & KADM5_LAST_PWD_CHANGE) {
622c19800e8SDoug Rabson abort (); /* XXX */
623c19800e8SDoug Rabson }
624c19800e8SDoug Rabson if (mask & KADM5_ATTRIBUTES) {
625c19800e8SDoug Rabson ent.entry.flags = log_ent.entry.flags;
626c19800e8SDoug Rabson }
627c19800e8SDoug Rabson if (mask & KADM5_MAX_LIFE) {
628b528cefcSMark Murray if (log_ent.entry.max_life == NULL) {
6295e9cd1aeSAssar Westerlund ent.entry.max_life = NULL;
630b528cefcSMark Murray } else {
631c19800e8SDoug Rabson if (ent.entry.max_life == NULL) {
632c19800e8SDoug Rabson ent.entry.max_life = malloc (sizeof(*ent.entry.max_life));
633c19800e8SDoug Rabson if (ent.entry.max_life == NULL) {
634c19800e8SDoug Rabson ret = ENOMEM;
635c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "out of memory");
636c19800e8SDoug Rabson goto out;
637c19800e8SDoug Rabson }
638b528cefcSMark Murray }
639c19800e8SDoug Rabson *ent.entry.max_life = *log_ent.entry.max_life;
640c19800e8SDoug Rabson }
641c19800e8SDoug Rabson }
642c19800e8SDoug Rabson if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) {
643c19800e8SDoug Rabson if (ent.entry.modified_by == NULL) {
644c19800e8SDoug Rabson ent.entry.modified_by = malloc(sizeof(*ent.entry.modified_by));
645b528cefcSMark Murray if (ent.entry.modified_by == NULL) {
646b528cefcSMark Murray ret = ENOMEM;
647c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "out of memory");
648b528cefcSMark Murray goto out;
649b528cefcSMark Murray }
650b528cefcSMark Murray } else
651b528cefcSMark Murray free_Event(ent.entry.modified_by);
652b528cefcSMark Murray ret = copy_Event(log_ent.entry.modified_by, ent.entry.modified_by);
653b528cefcSMark Murray if (ret) {
654b528cefcSMark Murray krb5_set_error_message(context->context, ret, "out of memory");
655b528cefcSMark Murray goto out;
656b528cefcSMark Murray }
657b528cefcSMark Murray }
658b528cefcSMark Murray if (mask & KADM5_KVNO) {
659b528cefcSMark Murray ent.entry.kvno = log_ent.entry.kvno;
660b528cefcSMark Murray }
661b528cefcSMark Murray if (mask & KADM5_MKVNO) {
662c19800e8SDoug Rabson abort (); /* XXX */
663c19800e8SDoug Rabson }
6645e9cd1aeSAssar Westerlund if (mask & KADM5_AUX_ATTRIBUTES) {
665c19800e8SDoug Rabson abort (); /* XXX */
666c19800e8SDoug Rabson }
667c19800e8SDoug Rabson if (mask & KADM5_POLICY) {
668c19800e8SDoug Rabson abort (); /* XXX */
669c19800e8SDoug Rabson }
670c19800e8SDoug Rabson if (mask & KADM5_POLICY_CLR) {
671c19800e8SDoug Rabson abort (); /* XXX */
672c19800e8SDoug Rabson }
673c19800e8SDoug Rabson if (mask & KADM5_MAX_RLIFE) {
674b528cefcSMark Murray if (log_ent.entry.max_renew == NULL) {
6755e9cd1aeSAssar Westerlund ent.entry.max_renew = NULL;
676b528cefcSMark Murray } else {
677b528cefcSMark Murray if (ent.entry.max_renew == NULL) {
678b528cefcSMark Murray ent.entry.max_renew = malloc (sizeof(*ent.entry.max_renew));
679b528cefcSMark Murray if (ent.entry.max_renew == NULL) {
680b528cefcSMark Murray ret = ENOMEM;
681b528cefcSMark Murray krb5_set_error_message(context->context, ret, "out of memory");
682b528cefcSMark Murray goto out;
683b528cefcSMark Murray }
684b528cefcSMark Murray }
685b528cefcSMark Murray *ent.entry.max_renew = *log_ent.entry.max_renew;
686c19800e8SDoug Rabson }
687b528cefcSMark Murray }
688b528cefcSMark Murray if (mask & KADM5_LAST_SUCCESS) {
689c19800e8SDoug Rabson abort (); /* XXX */
690c19800e8SDoug Rabson }
691c19800e8SDoug Rabson if (mask & KADM5_LAST_FAILED) {
692b528cefcSMark Murray abort (); /* XXX */
693c19800e8SDoug Rabson }
694b528cefcSMark Murray if (mask & KADM5_FAIL_AUTH_COUNT) {
695c19800e8SDoug Rabson abort (); /* XXX */
696c19800e8SDoug Rabson }
697c19800e8SDoug Rabson if (mask & KADM5_KEY_DATA) {
698c19800e8SDoug Rabson size_t num;
699c19800e8SDoug Rabson size_t i;
700b528cefcSMark Murray
701c19800e8SDoug Rabson for (i = 0; i < ent.entry.keys.len; ++i)
702c19800e8SDoug Rabson free_Key(&ent.entry.keys.val[i]);
703c19800e8SDoug Rabson free (ent.entry.keys.val);
704c19800e8SDoug Rabson
705c19800e8SDoug Rabson num = log_ent.entry.keys.len;
706c19800e8SDoug Rabson
707c19800e8SDoug Rabson ent.entry.keys.len = num;
708c19800e8SDoug Rabson ent.entry.keys.val = malloc(len * sizeof(*ent.entry.keys.val));
709c19800e8SDoug Rabson if (ent.entry.keys.val == NULL) {
710c19800e8SDoug Rabson krb5_set_error_message(context->context, ENOMEM, "out of memory");
711c19800e8SDoug Rabson return ENOMEM;
712c19800e8SDoug Rabson }
713c19800e8SDoug Rabson for (i = 0; i < ent.entry.keys.len; ++i) {
714c19800e8SDoug Rabson ret = copy_Key(&log_ent.entry.keys.val[i],
715c19800e8SDoug Rabson &ent.entry.keys.val[i]);
716c19800e8SDoug Rabson if (ret) {
717c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "out of memory");
718c19800e8SDoug Rabson goto out;
719c19800e8SDoug Rabson }
720c19800e8SDoug Rabson }
721c19800e8SDoug Rabson }
722c19800e8SDoug Rabson if ((mask & KADM5_TL_DATA) && log_ent.entry.extensions) {
723c19800e8SDoug Rabson HDB_extensions *es = ent.entry.extensions;
724c19800e8SDoug Rabson
725c19800e8SDoug Rabson ent.entry.extensions = calloc(1, sizeof(*ent.entry.extensions));
726c19800e8SDoug Rabson if (ent.entry.extensions == NULL)
727c19800e8SDoug Rabson goto out;
728c19800e8SDoug Rabson
729c19800e8SDoug Rabson ret = copy_HDB_extensions(log_ent.entry.extensions,
730c19800e8SDoug Rabson ent.entry.extensions);
731b528cefcSMark Murray if (ret) {
732c19800e8SDoug Rabson krb5_set_error_message(context->context, ret, "out of memory");
733b528cefcSMark Murray free(ent.entry.extensions);
734b528cefcSMark Murray ent.entry.extensions = es;
735b528cefcSMark Murray goto out;
736b528cefcSMark Murray }
737b528cefcSMark Murray if (es) {
738b528cefcSMark Murray free_HDB_extensions(es);
739c19800e8SDoug Rabson free(es);
7405e9cd1aeSAssar Westerlund }
7415e9cd1aeSAssar Westerlund }
7425e9cd1aeSAssar Westerlund ret = context->db->hdb_store(context->context, context->db,
7435e9cd1aeSAssar Westerlund HDB_F_REPLACE, &ent);
7445e9cd1aeSAssar Westerlund out:
7455e9cd1aeSAssar Westerlund hdb_free_entry (context->context, &ent);
7465e9cd1aeSAssar Westerlund hdb_free_entry (context->context, &log_ent);
7475e9cd1aeSAssar Westerlund return ret;
7485e9cd1aeSAssar Westerlund }
7495e9cd1aeSAssar Westerlund
7505e9cd1aeSAssar Westerlund /*
7515e9cd1aeSAssar Westerlund * Add a `nop' operation to the log. Does not close the log.
7525e9cd1aeSAssar Westerlund */
7535e9cd1aeSAssar Westerlund
7545e9cd1aeSAssar Westerlund kadm5_ret_t
kadm5_log_nop(kadm5_server_context * context)7555e9cd1aeSAssar Westerlund kadm5_log_nop (kadm5_server_context *context)
7565e9cd1aeSAssar Westerlund {
7575e9cd1aeSAssar Westerlund krb5_storage *sp;
7585e9cd1aeSAssar Westerlund kadm5_ret_t ret;
7595e9cd1aeSAssar Westerlund kadm5_log_context *log_context = &context->log_context;
7605e9cd1aeSAssar Westerlund
7615e9cd1aeSAssar Westerlund sp = krb5_storage_emem();
7625e9cd1aeSAssar Westerlund ret = kadm5_log_preamble (context, sp, kadm_nop);
7635e9cd1aeSAssar Westerlund if (ret) {
764c19800e8SDoug Rabson krb5_storage_free (sp);
7655e9cd1aeSAssar Westerlund return ret;
7665e9cd1aeSAssar Westerlund }
7675e9cd1aeSAssar Westerlund krb5_store_int32 (sp, 0);
7685e9cd1aeSAssar Westerlund krb5_store_int32 (sp, 0);
7695e9cd1aeSAssar Westerlund ret = kadm5_log_postamble (log_context, sp);
7705e9cd1aeSAssar Westerlund if (ret) {
7715e9cd1aeSAssar Westerlund krb5_storage_free (sp);
772c19800e8SDoug Rabson return ret;
7735e9cd1aeSAssar Westerlund }
774c19800e8SDoug Rabson ret = kadm5_log_flush (log_context, sp);
775c19800e8SDoug Rabson krb5_storage_free (sp);
7765e9cd1aeSAssar Westerlund
7775e9cd1aeSAssar Westerlund return ret;
7785e9cd1aeSAssar Westerlund }
7795e9cd1aeSAssar Westerlund
7805e9cd1aeSAssar Westerlund /*
7815e9cd1aeSAssar Westerlund * Read a `nop' log operation from `sp' and apply it.
782b528cefcSMark Murray */
783b528cefcSMark Murray
784b528cefcSMark Murray static kadm5_ret_t
kadm5_log_replay_nop(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)785b528cefcSMark Murray kadm5_log_replay_nop (kadm5_server_context *context,
786b528cefcSMark Murray uint32_t ver,
787b528cefcSMark Murray uint32_t len,
788c19800e8SDoug Rabson krb5_storage *sp)
789b528cefcSMark Murray {
790b528cefcSMark Murray return 0;
791c19800e8SDoug Rabson }
792c19800e8SDoug Rabson
793c19800e8SDoug Rabson /*
794c19800e8SDoug Rabson * Call `func' for each log record in the log in `context'
795b528cefcSMark Murray */
796b528cefcSMark Murray
797b528cefcSMark Murray kadm5_ret_t
kadm5_log_foreach(kadm5_server_context * context,void (* func)(kadm5_server_context * server_context,uint32_t ver,time_t timestamp,enum kadm_ops op,uint32_t len,krb5_storage *,void *),void * ctx)798b528cefcSMark Murray kadm5_log_foreach (kadm5_server_context *context,
799b528cefcSMark Murray void (*func)(kadm5_server_context *server_context,
800b528cefcSMark Murray uint32_t ver,
801b528cefcSMark Murray time_t timestamp,
802c19800e8SDoug Rabson enum kadm_ops op,
803b528cefcSMark Murray uint32_t len,
804b528cefcSMark Murray krb5_storage *,
805b528cefcSMark Murray void *),
806b528cefcSMark Murray void *ctx)
807b528cefcSMark Murray {
808b528cefcSMark Murray int fd = context->log_context.log_fd;
809c19800e8SDoug Rabson krb5_storage *sp;
810c19800e8SDoug Rabson
811c19800e8SDoug Rabson lseek (fd, 0, SEEK_SET);
812c19800e8SDoug Rabson sp = krb5_storage_from_fd (fd);
813c19800e8SDoug Rabson for (;;) {
814c19800e8SDoug Rabson int32_t ver, timestamp, op, len, len2, ver2;
815c19800e8SDoug Rabson
816b528cefcSMark Murray if(krb5_ret_int32 (sp, &ver) != 0)
817c19800e8SDoug Rabson break;
818b528cefcSMark Murray krb5_ret_int32 (sp, ×tamp);
819b528cefcSMark Murray krb5_ret_int32 (sp, &op);
820b528cefcSMark Murray krb5_ret_int32 (sp, &len);
821b528cefcSMark Murray (*func)(context, ver, timestamp, op, len, sp, ctx);
822b528cefcSMark Murray krb5_ret_int32 (sp, &len2);
823b528cefcSMark Murray krb5_ret_int32 (sp, &ver2);
824b528cefcSMark Murray if (len != len2)
825b528cefcSMark Murray abort();
826b528cefcSMark Murray if (ver != ver2)
827b528cefcSMark Murray abort();
828b528cefcSMark Murray }
829b528cefcSMark Murray krb5_storage_free(sp);
830b528cefcSMark Murray return 0;
8318373020dSJacques Vidrine }
832b528cefcSMark Murray
833b528cefcSMark Murray /*
834b528cefcSMark Murray * Go to end of log.
835b528cefcSMark Murray */
836b528cefcSMark Murray
837c19800e8SDoug Rabson krb5_storage *
kadm5_log_goto_end(int fd)838c19800e8SDoug Rabson kadm5_log_goto_end (int fd)
839c19800e8SDoug Rabson {
840c19800e8SDoug Rabson krb5_storage *sp;
841b528cefcSMark Murray
842b528cefcSMark Murray sp = krb5_storage_from_fd (fd);
843b528cefcSMark Murray krb5_storage_seek(sp, 0, SEEK_END);
844c19800e8SDoug Rabson return sp;
845c19800e8SDoug Rabson }
846c19800e8SDoug Rabson
847b528cefcSMark Murray /*
848b528cefcSMark Murray * Return previous log entry.
849c19800e8SDoug Rabson *
850b528cefcSMark Murray * The pointer in `sp´ is assumed to be at the top of the entry before
851c19800e8SDoug Rabson * previous entry. On success, the `sp´ pointer is set to data portion
852c19800e8SDoug Rabson * of previous entry. In case of error, it's not changed at all.
853b528cefcSMark Murray */
854b528cefcSMark Murray
855c19800e8SDoug Rabson kadm5_ret_t
kadm5_log_previous(krb5_context context,krb5_storage * sp,uint32_t * ver,time_t * timestamp,enum kadm_ops * op,uint32_t * len)856c19800e8SDoug Rabson kadm5_log_previous (krb5_context context,
8578373020dSJacques Vidrine krb5_storage *sp,
858c19800e8SDoug Rabson uint32_t *ver,
859c19800e8SDoug Rabson time_t *timestamp,
860c19800e8SDoug Rabson enum kadm_ops *op,
861b528cefcSMark Murray uint32_t *len)
862c19800e8SDoug Rabson {
863b528cefcSMark Murray krb5_error_code ret;
864b528cefcSMark Murray off_t off, oldoff;
8658373020dSJacques Vidrine int32_t tmp;
866c19800e8SDoug Rabson
867c19800e8SDoug Rabson oldoff = krb5_storage_seek(sp, 0, SEEK_CUR);
868c19800e8SDoug Rabson
869c19800e8SDoug Rabson krb5_storage_seek(sp, -8, SEEK_CUR);
870c19800e8SDoug Rabson ret = krb5_ret_int32 (sp, &tmp);
871c19800e8SDoug Rabson if (ret)
872c19800e8SDoug Rabson goto end_of_storage;
873c19800e8SDoug Rabson *len = tmp;
874c19800e8SDoug Rabson ret = krb5_ret_int32 (sp, &tmp);
875c19800e8SDoug Rabson if (ret)
876c19800e8SDoug Rabson goto end_of_storage;
877c19800e8SDoug Rabson *ver = tmp;
878b528cefcSMark Murray off = 24 + *len;
879c19800e8SDoug Rabson krb5_storage_seek(sp, -off, SEEK_CUR);
880b528cefcSMark Murray ret = krb5_ret_int32 (sp, &tmp);
881c19800e8SDoug Rabson if (ret)
882c19800e8SDoug Rabson goto end_of_storage;
883c19800e8SDoug Rabson if ((uint32_t)tmp != *ver) {
884c19800e8SDoug Rabson krb5_storage_seek(sp, oldoff, SEEK_SET);
885c19800e8SDoug Rabson krb5_set_error_message(context, KADM5_BAD_DB,
886c19800e8SDoug Rabson "kadm5_log_previous: log entry "
887c19800e8SDoug Rabson "have consistency failure, version number wrong "
888c19800e8SDoug Rabson "(tmp %lu ver %lu)",
889c19800e8SDoug Rabson (unsigned long)tmp,
890b528cefcSMark Murray (unsigned long)*ver);
891c19800e8SDoug Rabson return KADM5_BAD_DB;
892c19800e8SDoug Rabson }
893c19800e8SDoug Rabson ret = krb5_ret_int32 (sp, &tmp);
894c19800e8SDoug Rabson if (ret)
895c19800e8SDoug Rabson goto end_of_storage;
896c19800e8SDoug Rabson *timestamp = tmp;
897b528cefcSMark Murray ret = krb5_ret_int32 (sp, &tmp);
898b528cefcSMark Murray if (ret)
899b528cefcSMark Murray goto end_of_storage;
900b528cefcSMark Murray *op = tmp;
901b528cefcSMark Murray ret = krb5_ret_int32 (sp, &tmp);
902b528cefcSMark Murray if (ret)
903b528cefcSMark Murray goto end_of_storage;
904b528cefcSMark Murray if ((uint32_t)tmp != *len) {
905b528cefcSMark Murray krb5_storage_seek(sp, oldoff, SEEK_SET);
906c19800e8SDoug Rabson krb5_set_error_message(context, KADM5_BAD_DB,
907c19800e8SDoug Rabson "kadm5_log_previous: log entry "
908b528cefcSMark Murray "have consistency failure, length wrong");
909b528cefcSMark Murray return KADM5_BAD_DB;
910b528cefcSMark Murray }
911b528cefcSMark Murray return 0;
912b528cefcSMark Murray
913b528cefcSMark Murray end_of_storage:
914b528cefcSMark Murray krb5_storage_seek(sp, oldoff, SEEK_SET);
915b528cefcSMark Murray krb5_set_error_message(context, ret, "kadm5_log_previous: end of storage "
916b528cefcSMark Murray "reached before end");
917b528cefcSMark Murray return ret;
918b528cefcSMark Murray }
9195e9cd1aeSAssar Westerlund
9205e9cd1aeSAssar Westerlund /*
921b528cefcSMark Murray * Replay a record from the log
922c19800e8SDoug Rabson */
923c19800e8SDoug Rabson
924b528cefcSMark Murray kadm5_ret_t
kadm5_log_replay(kadm5_server_context * context,enum kadm_ops op,uint32_t ver,uint32_t len,krb5_storage * sp)925b528cefcSMark Murray kadm5_log_replay (kadm5_server_context *context,
926b528cefcSMark Murray enum kadm_ops op,
9275e9cd1aeSAssar Westerlund uint32_t ver,
9285e9cd1aeSAssar Westerlund uint32_t len,
9295e9cd1aeSAssar Westerlund krb5_storage *sp)
9305e9cd1aeSAssar Westerlund {
9315e9cd1aeSAssar Westerlund switch (op) {
9325e9cd1aeSAssar Westerlund case kadm_create :
9335e9cd1aeSAssar Westerlund return kadm5_log_replay_create (context, ver, len, sp);
9345e9cd1aeSAssar Westerlund case kadm_delete :
9355e9cd1aeSAssar Westerlund return kadm5_log_replay_delete (context, ver, len, sp);
936c19800e8SDoug Rabson case kadm_rename :
9375e9cd1aeSAssar Westerlund return kadm5_log_replay_rename (context, ver, len, sp);
9385e9cd1aeSAssar Westerlund case kadm_modify :
9395e9cd1aeSAssar Westerlund return kadm5_log_replay_modify (context, ver, len, sp);
9405e9cd1aeSAssar Westerlund case kadm_nop :
9415e9cd1aeSAssar Westerlund return kadm5_log_replay_nop (context, ver, len, sp);
9425e9cd1aeSAssar Westerlund default :
9435e9cd1aeSAssar Westerlund krb5_set_error_message(context->context, KADM5_FAILURE,
9445e9cd1aeSAssar Westerlund "Unsupported replay op %d", (int)op);
9455e9cd1aeSAssar Westerlund return KADM5_FAILURE;
9465e9cd1aeSAssar Westerlund }
9475e9cd1aeSAssar Westerlund }
9485e9cd1aeSAssar Westerlund
9495e9cd1aeSAssar Westerlund /*
950c19800e8SDoug Rabson * truncate the log - i.e. create an empty file with just (nop vno + 2)
9515e9cd1aeSAssar Westerlund */
9525e9cd1aeSAssar Westerlund
9535e9cd1aeSAssar Westerlund kadm5_ret_t
kadm5_log_truncate(kadm5_server_context * server_context)9545e9cd1aeSAssar Westerlund kadm5_log_truncate (kadm5_server_context *server_context)
9555e9cd1aeSAssar Westerlund {
9565e9cd1aeSAssar Westerlund kadm5_ret_t ret;
9575e9cd1aeSAssar Westerlund uint32_t vno;
9585e9cd1aeSAssar Westerlund
9595e9cd1aeSAssar Westerlund ret = kadm5_log_init (server_context);
9605e9cd1aeSAssar Westerlund if (ret)
9615e9cd1aeSAssar Westerlund return ret;
9625e9cd1aeSAssar Westerlund
9635e9cd1aeSAssar Westerlund ret = kadm5_log_get_version (server_context, &vno);
964c19800e8SDoug Rabson if (ret)
965c19800e8SDoug Rabson return ret;
966c19800e8SDoug Rabson
967c19800e8SDoug Rabson ret = kadm5_log_reinit (server_context);
968c19800e8SDoug Rabson if (ret)
969c19800e8SDoug Rabson return ret;
970c19800e8SDoug Rabson
971c19800e8SDoug Rabson ret = kadm5_log_set_version (server_context, vno);
972c19800e8SDoug Rabson if (ret)
973c19800e8SDoug Rabson return ret;
974c19800e8SDoug Rabson
975c19800e8SDoug Rabson ret = kadm5_log_nop (server_context);
976c19800e8SDoug Rabson if (ret)
977c19800e8SDoug Rabson return ret;
978c19800e8SDoug Rabson
979c19800e8SDoug Rabson ret = kadm5_log_end (server_context);
980c19800e8SDoug Rabson if (ret)
981c19800e8SDoug Rabson return ret;
982c19800e8SDoug Rabson return 0;
983
984 }
985
986 #ifndef NO_UNIX_SOCKETS
987
988 static char *default_signal = NULL;
989 static HEIMDAL_MUTEX signal_mutex = HEIMDAL_MUTEX_INITIALIZER;
990
991 const char *
kadm5_log_signal_socket(krb5_context context)992 kadm5_log_signal_socket(krb5_context context)
993 {
994 HEIMDAL_MUTEX_lock(&signal_mutex);
995 if (!default_signal)
996 asprintf(&default_signal, "%s/signal", hdb_db_dir(context));
997 HEIMDAL_MUTEX_unlock(&signal_mutex);
998
999 return krb5_config_get_string_default(context,
1000 NULL,
1001 default_signal,
1002 "kdc",
1003 "signal_socket",
1004 NULL);
1005 }
1006
1007 #else /* NO_UNIX_SOCKETS */
1008
1009 #define SIGNAL_SOCKET_HOST "127.0.0.1"
1010 #define SIGNAL_SOCKET_PORT "12701"
1011
1012 kadm5_ret_t
kadm5_log_signal_socket_info(krb5_context context,int server_end,struct addrinfo ** ret_addrs)1013 kadm5_log_signal_socket_info(krb5_context context,
1014 int server_end,
1015 struct addrinfo **ret_addrs)
1016 {
1017 struct addrinfo hints;
1018 struct addrinfo *addrs = NULL;
1019 kadm5_ret_t ret = KADM5_FAILURE;
1020 int wsret;
1021
1022 memset(&hints, 0, sizeof(hints));
1023
1024 hints.ai_flags = AI_NUMERICHOST;
1025 if (server_end)
1026 hints.ai_flags |= AI_PASSIVE;
1027 hints.ai_family = AF_INET;
1028 hints.ai_socktype = SOCK_STREAM;
1029 hints.ai_protocol = IPPROTO_TCP;
1030
1031 wsret = getaddrinfo(SIGNAL_SOCKET_HOST,
1032 SIGNAL_SOCKET_PORT,
1033 &hints, &addrs);
1034
1035 if (wsret != 0) {
1036 krb5_set_error_message(context, KADM5_FAILURE,
1037 "%s", gai_strerror(wsret));
1038 goto done;
1039 }
1040
1041 if (addrs == NULL) {
1042 krb5_set_error_message(context, KADM5_FAILURE,
1043 "getaddrinfo() failed to return address list");
1044 goto done;
1045 }
1046
1047 *ret_addrs = addrs;
1048 addrs = NULL;
1049 ret = 0;
1050
1051 done:
1052 if (addrs)
1053 freeaddrinfo(addrs);
1054 return ret;
1055 }
1056
1057 #endif
1058