xref: /freebsd-src/crypto/heimdal/lib/kadm5/log.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov  * 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 
37*ae771770SStanislav Sedov 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) {
102*ae771770SStanislav Sedov 	ret = errno;
103*ae771770SStanislav Sedov 	krb5_set_error_message(context->context, ret, "kadm5_log_init: open %s",
104c19800e8SDoug Rabson 			      log_context->log_file);
105*ae771770SStanislav Sedov 	return ret;
106c19800e8SDoug Rabson     }
107b528cefcSMark Murray     if (flock (fd, LOCK_EX) < 0) {
108*ae771770SStanislav Sedov 	ret = errno;
109*ae771770SStanislav Sedov 	krb5_set_error_message(context->context, ret, "kadm5_log_init: flock %s",
110c19800e8SDoug Rabson 			       log_context->log_file);
111b528cefcSMark Murray 	close (fd);
112b528cefcSMark Murray 	return errno;
113b528cefcSMark Murray     }
114b528cefcSMark Murray 
1155e9cd1aeSAssar Westerlund     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 }
122b528cefcSMark Murray 
123b528cefcSMark Murray 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;
1285e9cd1aeSAssar Westerlund 
1295e9cd1aeSAssar Westerlund     if (log_context->log_fd != -1) {
130c19800e8SDoug Rabson 	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 
1475e9cd1aeSAssar Westerlund 
1485e9cd1aeSAssar Westerlund 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;
196*ae771770SStanislav Sedov     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);
201*ae771770SStanislav Sedov     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     }
209*ae771770SStanislav Sedov 
210b528cefcSMark Murray     /*
211b528cefcSMark Murray      * Try to send a signal to any running `ipropd-master'
212b528cefcSMark Murray      */
213*ae771770SStanislav Sedov #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));
220*ae771770SStanislav Sedov #else
221*ae771770SStanislav Sedov     sendto (log_context->socket_fd,
222*ae771770SStanislav Sedov 	    (void *)&log_context->version,
223*ae771770SStanislav Sedov 	    sizeof(log_context->version),
224*ae771770SStanislav Sedov 	    0,
225*ae771770SStanislav Sedov 	    log_context->socket_info->ai_addr,
226*ae771770SStanislav Sedov 	    log_context->socket_info->ai_addrlen);
227*ae771770SStanislav Sedov #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();
247b528cefcSMark Murray     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);
2598373020dSJacques Vidrine     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);
268b528cefcSMark Murray     krb5_storage_free (sp);
269b528cefcSMark Murray     if (ret)
270b528cefcSMark Murray 	return ret;
271b528cefcSMark Murray     ret = kadm5_log_end (context);
272b528cefcSMark Murray     return ret;
273b528cefcSMark Murray }
274b528cefcSMark Murray 
275b528cefcSMark Murray /*
276b528cefcSMark Murray  * Read the data of a create log record from `sp' and change the
277b528cefcSMark Murray  * database.
278b528cefcSMark Murray  */
279b528cefcSMark Murray 
280c19800e8SDoug Rabson static kadm5_ret_t
kadm5_log_replay_create(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)281b528cefcSMark Murray kadm5_log_replay_create (kadm5_server_context *context,
282c19800e8SDoug Rabson 			 uint32_t ver,
283c19800e8SDoug Rabson 			 uint32_t len,
284b528cefcSMark Murray 			 krb5_storage *sp)
285b528cefcSMark Murray {
286b528cefcSMark Murray     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 
292bbd80c28SJacques Vidrine     ret = krb5_data_alloc (&data, len);
293c19800e8SDoug Rabson     if (ret) {
294*ae771770SStanislav Sedov 	krb5_set_error_message(context->context, ret, "out of memory");
295bbd80c28SJacques Vidrine 	return ret;
296c19800e8SDoug Rabson     }
2978373020dSJacques Vidrine     krb5_storage_read (sp, data.data, len);
298c19800e8SDoug Rabson     ret = hdb_value2entry (context->context, &data, &ent.entry);
299b528cefcSMark Murray     krb5_data_free(&data);
300c19800e8SDoug Rabson     if (ret) {
301*ae771770SStanislav Sedov 	krb5_set_error_message(context->context, ret,
302c19800e8SDoug Rabson 			       "Unmarshaling hdb entry failed");
303b528cefcSMark Murray 	return ret;
304c19800e8SDoug Rabson     }
305c19800e8SDoug Rabson     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  */
313b528cefcSMark Murray 
314b528cefcSMark Murray kadm5_ret_t
kadm5_log_delete(kadm5_server_context * context,krb5_principal princ)315b528cefcSMark Murray kadm5_log_delete (kadm5_server_context *context,
316b528cefcSMark Murray 		  krb5_principal princ)
317b528cefcSMark Murray {
318b528cefcSMark Murray     krb5_storage *sp;
319b528cefcSMark Murray     kadm5_ret_t ret;
320b528cefcSMark Murray     off_t off;
321b528cefcSMark Murray     off_t len;
322b528cefcSMark Murray     kadm5_log_context *log_context = &context->log_context;
323b528cefcSMark Murray 
324b528cefcSMark Murray     sp = krb5_storage_emem();
325c19800e8SDoug Rabson     if (sp == NULL)
326c19800e8SDoug Rabson 	return ENOMEM;
327b528cefcSMark Murray     ret = kadm5_log_preamble (context, sp, kadm_delete);
328c19800e8SDoug Rabson     if (ret)
329c19800e8SDoug Rabson 	goto out;
330c19800e8SDoug Rabson     ret = krb5_store_int32 (sp, 0);
331c19800e8SDoug Rabson     if (ret)
332c19800e8SDoug Rabson 	goto out;
3338373020dSJacques Vidrine     off = krb5_storage_seek (sp, 0, SEEK_CUR);
334c19800e8SDoug Rabson     ret = krb5_store_principal (sp, princ);
335c19800e8SDoug Rabson     if (ret)
336c19800e8SDoug Rabson 	goto out;
3378373020dSJacques Vidrine     len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
3388373020dSJacques Vidrine     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);
343c19800e8SDoug Rabson     ret = krb5_store_int32 (sp, len);
344c19800e8SDoug Rabson     if (ret)
345c19800e8SDoug Rabson 	goto out;
346c19800e8SDoug Rabson     ret = kadm5_log_postamble (log_context, sp);
347c19800e8SDoug Rabson     if (ret)
348c19800e8SDoug Rabson 	goto out;
349c19800e8SDoug Rabson     ret = kadm5_log_flush (log_context, sp);
350c19800e8SDoug Rabson     if (ret)
351c19800e8SDoug Rabson 	goto out;
352b528cefcSMark Murray     ret = kadm5_log_end (context);
353c19800e8SDoug Rabson out:
354c19800e8SDoug Rabson     krb5_storage_free (sp);
355b528cefcSMark Murray     return ret;
356b528cefcSMark Murray }
357b528cefcSMark Murray 
358b528cefcSMark Murray /*
359b528cefcSMark Murray  * Read a `delete' log operation from `sp' and apply it.
360b528cefcSMark Murray  */
361b528cefcSMark Murray 
362c19800e8SDoug Rabson static kadm5_ret_t
kadm5_log_replay_delete(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)363b528cefcSMark Murray kadm5_log_replay_delete (kadm5_server_context *context,
364c19800e8SDoug Rabson 			 uint32_t ver,
365c19800e8SDoug Rabson 			 uint32_t len,
366b528cefcSMark Murray 			 krb5_storage *sp)
367b528cefcSMark Murray {
368b528cefcSMark Murray     krb5_error_code ret;
369c19800e8SDoug Rabson     krb5_principal principal;
370b528cefcSMark Murray 
371c19800e8SDoug Rabson     ret = krb5_ret_principal (sp, &principal);
372c19800e8SDoug Rabson     if (ret) {
373*ae771770SStanislav Sedov 	krb5_set_error_message(context->context,  ret, "Failed to read deleted "
374c19800e8SDoug Rabson 			       "principal from log version: %ld",  (long)ver);
375c19800e8SDoug Rabson 	return ret;
376c19800e8SDoug Rabson     }
377b528cefcSMark Murray 
378c19800e8SDoug Rabson     ret = context->db->hdb_remove(context->context, context->db, principal);
379c19800e8SDoug Rabson     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 
387b528cefcSMark Murray kadm5_ret_t
kadm5_log_rename(kadm5_server_context * context,krb5_principal source,hdb_entry * ent)388b528cefcSMark Murray kadm5_log_rename (kadm5_server_context *context,
389b528cefcSMark Murray 		  krb5_principal source,
390b528cefcSMark Murray 		  hdb_entry *ent)
391b528cefcSMark Murray {
392b528cefcSMark Murray     krb5_storage *sp;
393b528cefcSMark Murray     kadm5_ret_t ret;
394b528cefcSMark Murray     off_t off;
395b528cefcSMark Murray     off_t len;
396b528cefcSMark Murray     krb5_data value;
397b528cefcSMark Murray     kadm5_log_context *log_context = &context->log_context;
398b528cefcSMark Murray 
399c19800e8SDoug Rabson     krb5_data_zero(&value);
400c19800e8SDoug Rabson 
401b528cefcSMark Murray     sp = krb5_storage_emem();
402b528cefcSMark Murray     ret = hdb_entry2value (context->context, ent, &value);
403c19800e8SDoug Rabson     if (ret)
404c19800e8SDoug Rabson 	goto failed;
405c19800e8SDoug Rabson 
406b528cefcSMark Murray     ret = kadm5_log_preamble (context, sp, kadm_rename);
407c19800e8SDoug Rabson     if (ret)
408c19800e8SDoug Rabson 	goto failed;
409c19800e8SDoug Rabson 
410c19800e8SDoug Rabson     ret = krb5_store_int32 (sp, 0);
411c19800e8SDoug Rabson     if (ret)
412c19800e8SDoug Rabson 	goto failed;
4138373020dSJacques Vidrine     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 
4188373020dSJacques Vidrine     krb5_storage_write(sp, value.data, value.length);
4198373020dSJacques Vidrine     len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
420b528cefcSMark Murray 
4218373020dSJacques Vidrine     krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
422c19800e8SDoug Rabson     ret = krb5_store_int32 (sp, len);
423b528cefcSMark Murray     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;
434c19800e8SDoug Rabson 
435c19800e8SDoug Rabson     ret = kadm5_log_flush (log_context, sp);
436c19800e8SDoug Rabson     if (ret)
437c19800e8SDoug Rabson 	goto failed;
438c19800e8SDoug Rabson     krb5_storage_free (sp);
439c19800e8SDoug Rabson     krb5_data_free (&value);
440c19800e8SDoug Rabson 
441c19800e8SDoug Rabson     return kadm5_log_end (context);
442c19800e8SDoug Rabson 
443c19800e8SDoug Rabson failed:
444c19800e8SDoug Rabson     krb5_data_free(&value);
445c19800e8SDoug Rabson     krb5_storage_free(sp);
446b528cefcSMark Murray     return ret;
447b528cefcSMark Murray }
448b528cefcSMark Murray 
449b528cefcSMark Murray /*
450b528cefcSMark Murray  * Read a `rename' log operation from `sp' and apply it.
451b528cefcSMark Murray  */
452b528cefcSMark Murray 
453c19800e8SDoug Rabson static kadm5_ret_t
kadm5_log_replay_rename(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)454b528cefcSMark Murray kadm5_log_replay_rename (kadm5_server_context *context,
455c19800e8SDoug Rabson 			 uint32_t ver,
456c19800e8SDoug Rabson 			 uint32_t len,
457b528cefcSMark Murray 			 krb5_storage *sp)
458b528cefcSMark Murray {
459b528cefcSMark Murray     krb5_error_code ret;
460b528cefcSMark Murray     krb5_principal source;
461c19800e8SDoug Rabson     hdb_entry_ex target_ent;
462b528cefcSMark Murray     krb5_data value;
463b528cefcSMark Murray     off_t off;
464b528cefcSMark Murray     size_t princ_len, data_len;
465b528cefcSMark Murray 
466c19800e8SDoug Rabson     memset(&target_ent, 0, sizeof(target_ent));
467c19800e8SDoug Rabson 
4688373020dSJacques Vidrine     off = krb5_storage_seek(sp, 0, SEEK_CUR);
469c19800e8SDoug Rabson     ret = krb5_ret_principal (sp, &source);
470c19800e8SDoug Rabson     if (ret) {
471*ae771770SStanislav Sedov 	krb5_set_error_message(context->context, ret, "Failed to read renamed "
472c19800e8SDoug Rabson 			       "principal in log, version: %ld", (long)ver);
473c19800e8SDoug Rabson 	return ret;
474c19800e8SDoug Rabson     }
4758373020dSJacques Vidrine     princ_len = krb5_storage_seek(sp, 0, SEEK_CUR) - off;
476b528cefcSMark Murray     data_len = len - princ_len;
477bbd80c28SJacques Vidrine     ret = krb5_data_alloc (&value, data_len);
478bbd80c28SJacques Vidrine     if (ret) {
479bbd80c28SJacques Vidrine 	krb5_free_principal (context->context, source);
480bbd80c28SJacques Vidrine 	return ret;
481bbd80c28SJacques Vidrine     }
4828373020dSJacques Vidrine     krb5_storage_read (sp, value.data, data_len);
483c19800e8SDoug Rabson     ret = hdb_value2entry (context->context, &value, &target_ent.entry);
484b528cefcSMark Murray     krb5_data_free(&value);
485b528cefcSMark Murray     if (ret) {
486b528cefcSMark Murray 	krb5_free_principal (context->context, source);
487b528cefcSMark Murray 	return ret;
488b528cefcSMark Murray     }
489c19800e8SDoug Rabson     ret = context->db->hdb_store (context->context, context->db,
490c19800e8SDoug Rabson 				  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     }
496c19800e8SDoug Rabson     ret = context->db->hdb_remove (context->context, context->db, source);
497b528cefcSMark Murray     krb5_free_principal (context->context, source);
498b528cefcSMark Murray     return ret;
499b528cefcSMark Murray }
500b528cefcSMark Murray 
501b528cefcSMark Murray 
502b528cefcSMark Murray /*
503b528cefcSMark Murray  * Add a `modify' operation to the log.
504b528cefcSMark Murray  */
505b528cefcSMark Murray 
506b528cefcSMark Murray 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,
509c19800e8SDoug Rabson 		  uint32_t mask)
510b528cefcSMark Murray {
511b528cefcSMark Murray     krb5_storage *sp;
512b528cefcSMark Murray     kadm5_ret_t ret;
513b528cefcSMark Murray     krb5_data value;
514c19800e8SDoug Rabson     uint32_t len;
515b528cefcSMark Murray     kadm5_log_context *log_context = &context->log_context;
516b528cefcSMark Murray 
517c19800e8SDoug Rabson     krb5_data_zero(&value);
518c19800e8SDoug Rabson 
519b528cefcSMark Murray     sp = krb5_storage_emem();
520b528cefcSMark Murray     ret = hdb_entry2value (context->context, ent, &value);
521b528cefcSMark Murray     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;
540c19800e8SDoug Rabson     ret = kadm5_log_postamble (log_context, sp);
541c19800e8SDoug Rabson     if (ret)
542c19800e8SDoug Rabson 	goto failed;
543c19800e8SDoug Rabson     ret = kadm5_log_flush (log_context, sp);
544c19800e8SDoug Rabson     if (ret)
545c19800e8SDoug Rabson 	goto failed;
546c19800e8SDoug Rabson     krb5_data_free(&value);
547c19800e8SDoug Rabson     krb5_storage_free (sp);
548c19800e8SDoug Rabson     return kadm5_log_end (context);
549c19800e8SDoug Rabson failed:
550c19800e8SDoug Rabson     krb5_data_free(&value);
551c19800e8SDoug Rabson     krb5_storage_free(sp);
552b528cefcSMark Murray     return ret;
553b528cefcSMark Murray }
554b528cefcSMark Murray 
555b528cefcSMark Murray /*
556b528cefcSMark Murray  * Read a `modify' log operation from `sp' and apply it.
557b528cefcSMark Murray  */
558b528cefcSMark Murray 
559c19800e8SDoug Rabson 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,
561c19800e8SDoug Rabson 			 uint32_t ver,
562c19800e8SDoug Rabson 			 uint32_t len,
563b528cefcSMark Murray 			 krb5_storage *sp)
564b528cefcSMark Murray {
565b528cefcSMark Murray     krb5_error_code ret;
566b528cefcSMark Murray     int32_t mask;
567b528cefcSMark Murray     krb5_data value;
568c19800e8SDoug Rabson     hdb_entry_ex ent, log_ent;
569c19800e8SDoug Rabson 
570c19800e8SDoug Rabson     memset(&log_ent, 0, sizeof(log_ent));
571b528cefcSMark Murray 
572b528cefcSMark Murray     krb5_ret_int32 (sp, &mask);
573b528cefcSMark Murray     len -= 4;
574bbd80c28SJacques Vidrine     ret = krb5_data_alloc (&value, len);
575c19800e8SDoug Rabson     if (ret) {
576*ae771770SStanislav Sedov 	krb5_set_error_message(context->context, ret, "out of memory");
577bbd80c28SJacques Vidrine 	return ret;
578c19800e8SDoug Rabson     }
5798373020dSJacques Vidrine     krb5_storage_read (sp, value.data, len);
580c19800e8SDoug Rabson     ret = hdb_value2entry (context->context, &value, &log_ent.entry);
581b528cefcSMark Murray     krb5_data_free(&value);
582b528cefcSMark Murray     if (ret)
583b528cefcSMark Murray 	return ret;
584c19800e8SDoug Rabson 
585c19800e8SDoug Rabson     memset(&ent, 0, sizeof(ent));
586*ae771770SStanislav Sedov     ret = context->db->hdb_fetch_kvno(context->context, context->db,
587c19800e8SDoug Rabson 				      log_ent.entry.principal,
588*ae771770SStanislav Sedov 				      HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
589b528cefcSMark Murray     if (ret)
590c19800e8SDoug Rabson 	goto out;
591b528cefcSMark Murray     if (mask & KADM5_PRINC_EXPIRE_TIME) {
592c19800e8SDoug Rabson 	if (log_ent.entry.valid_end == NULL) {
593c19800e8SDoug Rabson 	    ent.entry.valid_end = NULL;
5945e9cd1aeSAssar Westerlund 	} else {
595c19800e8SDoug Rabson 	    if (ent.entry.valid_end == NULL) {
596c19800e8SDoug Rabson 		ent.entry.valid_end = malloc(sizeof(*ent.entry.valid_end));
597c19800e8SDoug Rabson 		if (ent.entry.valid_end == NULL) {
598c19800e8SDoug Rabson 		    ret = ENOMEM;
599*ae771770SStanislav Sedov 		    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;
604b528cefcSMark Murray 	}
6055e9cd1aeSAssar Westerlund     }
606b528cefcSMark Murray     if (mask & KADM5_PW_EXPIRATION) {
607c19800e8SDoug Rabson 	if (log_ent.entry.pw_end == NULL) {
608c19800e8SDoug Rabson 	    ent.entry.pw_end = NULL;
6095e9cd1aeSAssar Westerlund 	} else {
610c19800e8SDoug Rabson 	    if (ent.entry.pw_end == NULL) {
611c19800e8SDoug Rabson 		ent.entry.pw_end = malloc(sizeof(*ent.entry.pw_end));
612c19800e8SDoug Rabson 		if (ent.entry.pw_end == NULL) {
613c19800e8SDoug Rabson 		    ret = ENOMEM;
614*ae771770SStanislav Sedov 		    krb5_set_error_message(context->context, ret, "out of memory");
615c19800e8SDoug Rabson 		    goto out;
616c19800e8SDoug Rabson 		}
617c19800e8SDoug Rabson 	    }
618c19800e8SDoug Rabson 	    *ent.entry.pw_end = *log_ent.entry.pw_end;
619b528cefcSMark Murray 	}
6205e9cd1aeSAssar Westerlund     }
621b528cefcSMark Murray     if (mask & KADM5_LAST_PWD_CHANGE) {
622b528cefcSMark Murray 	abort ();		/* XXX */
623b528cefcSMark Murray     }
624b528cefcSMark Murray     if (mask & KADM5_ATTRIBUTES) {
625c19800e8SDoug Rabson 	ent.entry.flags = log_ent.entry.flags;
626b528cefcSMark Murray     }
627b528cefcSMark Murray     if (mask & KADM5_MAX_LIFE) {
628c19800e8SDoug Rabson 	if (log_ent.entry.max_life == NULL) {
629c19800e8SDoug Rabson 	    ent.entry.max_life = NULL;
6305e9cd1aeSAssar Westerlund 	} 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;
635*ae771770SStanislav Sedov 		    krb5_set_error_message(context->context, ret, "out of memory");
636c19800e8SDoug Rabson 		    goto out;
637c19800e8SDoug Rabson 		}
638c19800e8SDoug Rabson 	    }
639c19800e8SDoug Rabson 	    *ent.entry.max_life = *log_ent.entry.max_life;
640b528cefcSMark Murray 	}
6415e9cd1aeSAssar Westerlund     }
642b528cefcSMark Murray     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));
645c19800e8SDoug Rabson 	    if (ent.entry.modified_by == NULL) {
646c19800e8SDoug Rabson 		ret = ENOMEM;
647*ae771770SStanislav Sedov 		krb5_set_error_message(context->context, ret, "out of memory");
648c19800e8SDoug Rabson 		goto out;
649c19800e8SDoug Rabson 	    }
650b528cefcSMark Murray 	} else
651c19800e8SDoug Rabson 	    free_Event(ent.entry.modified_by);
652c19800e8SDoug Rabson 	ret = copy_Event(log_ent.entry.modified_by, ent.entry.modified_by);
653c19800e8SDoug Rabson 	if (ret) {
654*ae771770SStanislav Sedov 	    krb5_set_error_message(context->context, ret, "out of memory");
655c19800e8SDoug Rabson 	    goto out;
656c19800e8SDoug Rabson 	}
657b528cefcSMark Murray     }
658b528cefcSMark Murray     if (mask & KADM5_KVNO) {
659c19800e8SDoug Rabson 	ent.entry.kvno = log_ent.entry.kvno;
660b528cefcSMark Murray     }
661b528cefcSMark Murray     if (mask & KADM5_MKVNO) {
662b528cefcSMark Murray 	abort ();		/* XXX */
663b528cefcSMark Murray     }
664b528cefcSMark Murray     if (mask & KADM5_AUX_ATTRIBUTES) {
665b528cefcSMark Murray 	abort ();		/* XXX */
666b528cefcSMark Murray     }
667b528cefcSMark Murray     if (mask & KADM5_POLICY) {
668b528cefcSMark Murray 	abort ();		/* XXX */
669b528cefcSMark Murray     }
670b528cefcSMark Murray     if (mask & KADM5_POLICY_CLR) {
671b528cefcSMark Murray 	abort ();		/* XXX */
672b528cefcSMark Murray     }
673b528cefcSMark Murray     if (mask & KADM5_MAX_RLIFE) {
674c19800e8SDoug Rabson 	if (log_ent.entry.max_renew == NULL) {
675c19800e8SDoug Rabson 	    ent.entry.max_renew = NULL;
6765e9cd1aeSAssar Westerlund 	} else {
677c19800e8SDoug Rabson 	    if (ent.entry.max_renew == NULL) {
678c19800e8SDoug Rabson 		ent.entry.max_renew = malloc (sizeof(*ent.entry.max_renew));
679c19800e8SDoug Rabson 		if (ent.entry.max_renew == NULL) {
680c19800e8SDoug Rabson 		    ret = ENOMEM;
681*ae771770SStanislav Sedov 		    krb5_set_error_message(context->context, ret, "out of memory");
682c19800e8SDoug Rabson 		    goto out;
683c19800e8SDoug Rabson 		}
684c19800e8SDoug Rabson 	    }
685c19800e8SDoug Rabson 	    *ent.entry.max_renew = *log_ent.entry.max_renew;
686b528cefcSMark Murray 	}
6875e9cd1aeSAssar Westerlund     }
688b528cefcSMark Murray     if (mask & KADM5_LAST_SUCCESS) {
689b528cefcSMark Murray 	abort ();		/* XXX */
690b528cefcSMark Murray     }
691b528cefcSMark Murray     if (mask & KADM5_LAST_FAILED) {
692b528cefcSMark Murray 	abort ();		/* XXX */
693b528cefcSMark Murray     }
694b528cefcSMark Murray     if (mask & KADM5_FAIL_AUTH_COUNT) {
695b528cefcSMark Murray 	abort ();		/* XXX */
696b528cefcSMark Murray     }
697b528cefcSMark Murray     if (mask & KADM5_KEY_DATA) {
698c19800e8SDoug Rabson 	size_t num;
699*ae771770SStanislav Sedov 	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);
704b528cefcSMark Murray 
705c19800e8SDoug Rabson 	num = log_ent.entry.keys.len;
706b528cefcSMark Murray 
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) {
710*ae771770SStanislav Sedov 	    krb5_set_error_message(context->context, ENOMEM, "out of memory");
711c19800e8SDoug Rabson 	    return ENOMEM;
712b528cefcSMark Murray 	}
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) {
717*ae771770SStanislav Sedov 		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);
731c19800e8SDoug Rabson 	if (ret) {
732*ae771770SStanislav Sedov 	    krb5_set_error_message(context->context, ret, "out of memory");
733c19800e8SDoug Rabson 	    free(ent.entry.extensions);
734c19800e8SDoug Rabson 	    ent.entry.extensions = es;
735c19800e8SDoug Rabson 	    goto out;
736c19800e8SDoug Rabson 	}
737c19800e8SDoug Rabson 	if (es) {
738c19800e8SDoug Rabson 	    free_HDB_extensions(es);
739c19800e8SDoug Rabson 	    free(es);
740c19800e8SDoug Rabson 	}
741c19800e8SDoug Rabson     }
742c19800e8SDoug Rabson     ret = context->db->hdb_store(context->context, context->db,
743b528cefcSMark Murray 				 HDB_F_REPLACE, &ent);
744c19800e8SDoug Rabson  out:
745b528cefcSMark Murray     hdb_free_entry (context->context, &ent);
746b528cefcSMark Murray     hdb_free_entry (context->context, &log_ent);
747b528cefcSMark Murray     return ret;
748b528cefcSMark Murray }
749b528cefcSMark Murray 
750b528cefcSMark Murray /*
751c19800e8SDoug Rabson  * 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) {
7645e9cd1aeSAssar Westerlund 	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);
7725e9cd1aeSAssar Westerlund 	return ret;
7735e9cd1aeSAssar Westerlund     }
7745e9cd1aeSAssar Westerlund     ret = kadm5_log_flush (log_context, sp);
7755e9cd1aeSAssar Westerlund     krb5_storage_free (sp);
776c19800e8SDoug Rabson 
7775e9cd1aeSAssar Westerlund     return ret;
7785e9cd1aeSAssar Westerlund }
7795e9cd1aeSAssar Westerlund 
7805e9cd1aeSAssar Westerlund /*
7815e9cd1aeSAssar Westerlund  * Read a `nop' log operation from `sp' and apply it.
7825e9cd1aeSAssar Westerlund  */
7835e9cd1aeSAssar Westerlund 
784c19800e8SDoug Rabson static kadm5_ret_t
kadm5_log_replay_nop(kadm5_server_context * context,uint32_t ver,uint32_t len,krb5_storage * sp)7855e9cd1aeSAssar Westerlund kadm5_log_replay_nop (kadm5_server_context *context,
786c19800e8SDoug Rabson 		      uint32_t ver,
787c19800e8SDoug Rabson 		      uint32_t len,
7885e9cd1aeSAssar Westerlund 		      krb5_storage *sp)
7895e9cd1aeSAssar Westerlund {
7905e9cd1aeSAssar Westerlund     return 0;
7915e9cd1aeSAssar Westerlund }
7925e9cd1aeSAssar Westerlund 
7935e9cd1aeSAssar Westerlund /*
794b528cefcSMark Murray  * 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,
800c19800e8SDoug Rabson 				uint32_t ver,
801b528cefcSMark Murray 				time_t timestamp,
802b528cefcSMark Murray 				enum kadm_ops op,
803c19800e8SDoug Rabson 				uint32_t len,
804c19800e8SDoug Rabson 				krb5_storage *,
805c19800e8SDoug Rabson 				void *),
806c19800e8SDoug Rabson 		   void *ctx)
807b528cefcSMark Murray {
808b528cefcSMark Murray     int fd = context->log_context.log_fd;
809b528cefcSMark Murray     krb5_storage *sp;
810b528cefcSMark Murray 
811b528cefcSMark Murray     lseek (fd, 0, SEEK_SET);
812b528cefcSMark Murray     sp = krb5_storage_from_fd (fd);
813b528cefcSMark Murray     for (;;) {
814c19800e8SDoug Rabson 	int32_t ver, timestamp, op, len, len2, ver2;
815b528cefcSMark Murray 
816b528cefcSMark Murray 	if(krb5_ret_int32 (sp, &ver) != 0)
817b528cefcSMark Murray 	    break;
818b528cefcSMark Murray 	krb5_ret_int32 (sp, &timestamp);
819b528cefcSMark Murray 	krb5_ret_int32 (sp, &op);
820b528cefcSMark Murray 	krb5_ret_int32 (sp, &len);
821c19800e8SDoug Rabson 	(*func)(context, ver, timestamp, op, len, sp, ctx);
822c19800e8SDoug Rabson 	krb5_ret_int32 (sp, &len2);
823c19800e8SDoug Rabson 	krb5_ret_int32 (sp, &ver2);
824c19800e8SDoug Rabson 	if (len != len2)
825c19800e8SDoug Rabson 	    abort();
826c19800e8SDoug Rabson 	if (ver != ver2)
827c19800e8SDoug Rabson 	    abort();
828b528cefcSMark Murray     }
829c19800e8SDoug Rabson     krb5_storage_free(sp);
830b528cefcSMark Murray     return 0;
831b528cefcSMark Murray }
832b528cefcSMark Murray 
833b528cefcSMark Murray /*
834b528cefcSMark Murray  * Go to end of log.
835b528cefcSMark Murray  */
836b528cefcSMark Murray 
837b528cefcSMark Murray krb5_storage *
kadm5_log_goto_end(int fd)838b528cefcSMark Murray kadm5_log_goto_end (int fd)
839b528cefcSMark Murray {
840b528cefcSMark Murray     krb5_storage *sp;
841b528cefcSMark Murray 
842b528cefcSMark Murray     sp = krb5_storage_from_fd (fd);
8438373020dSJacques Vidrine     krb5_storage_seek(sp, 0, SEEK_END);
844b528cefcSMark Murray     return sp;
845b528cefcSMark Murray }
846b528cefcSMark Murray 
847b528cefcSMark Murray /*
848b528cefcSMark Murray  * Return previous log entry.
849c19800e8SDoug Rabson  *
850*ae771770SStanislav Sedov  * The pointer in `sp´ is assumed to be at the top of the entry before
851*ae771770SStanislav Sedov  * 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 
855b528cefcSMark Murray 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,
857c19800e8SDoug Rabson 		    krb5_storage *sp,
858c19800e8SDoug Rabson 		    uint32_t *ver,
859b528cefcSMark Murray 		    time_t *timestamp,
860b528cefcSMark Murray 		    enum kadm_ops *op,
861c19800e8SDoug Rabson 		    uint32_t *len)
862b528cefcSMark Murray {
863c19800e8SDoug Rabson     krb5_error_code ret;
864c19800e8SDoug Rabson     off_t off, oldoff;
865b528cefcSMark Murray     int32_t tmp;
866b528cefcSMark Murray 
867c19800e8SDoug Rabson     oldoff = krb5_storage_seek(sp, 0, SEEK_CUR);
868c19800e8SDoug Rabson 
8698373020dSJacques Vidrine     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;
873b528cefcSMark Murray     *len = tmp;
874c19800e8SDoug Rabson     ret = krb5_ret_int32 (sp, &tmp);
875*ae771770SStanislav Sedov     if (ret)
876*ae771770SStanislav Sedov 	goto end_of_storage;
877b528cefcSMark Murray     *ver = tmp;
878b528cefcSMark Murray     off = 24 + *len;
8798373020dSJacques Vidrine     krb5_storage_seek(sp, -off, SEEK_CUR);
880c19800e8SDoug Rabson     ret = krb5_ret_int32 (sp, &tmp);
881c19800e8SDoug Rabson     if (ret)
882c19800e8SDoug Rabson 	goto end_of_storage;
883*ae771770SStanislav Sedov     if ((uint32_t)tmp != *ver) {
884c19800e8SDoug Rabson 	krb5_storage_seek(sp, oldoff, SEEK_SET);
885*ae771770SStanislav Sedov 	krb5_set_error_message(context, KADM5_BAD_DB,
886*ae771770SStanislav Sedov 			       "kadm5_log_previous: log entry "
887*ae771770SStanislav Sedov 			       "have consistency failure, version number wrong "
888*ae771770SStanislav Sedov 			       "(tmp %lu ver %lu)",
889*ae771770SStanislav Sedov 			       (unsigned long)tmp,
890*ae771770SStanislav Sedov 			       (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;
896b528cefcSMark Murray     *timestamp = tmp;
897c19800e8SDoug Rabson     ret = krb5_ret_int32 (sp, &tmp);
898*ae771770SStanislav Sedov     if (ret)
899*ae771770SStanislav Sedov 	goto end_of_storage;
900b528cefcSMark Murray     *op = tmp;
901c19800e8SDoug Rabson     ret = krb5_ret_int32 (sp, &tmp);
902c19800e8SDoug Rabson     if (ret)
903c19800e8SDoug Rabson 	goto end_of_storage;
904*ae771770SStanislav Sedov     if ((uint32_t)tmp != *len) {
905c19800e8SDoug Rabson 	krb5_storage_seek(sp, oldoff, SEEK_SET);
906*ae771770SStanislav Sedov 	krb5_set_error_message(context, KADM5_BAD_DB,
907*ae771770SStanislav Sedov 			       "kadm5_log_previous: log entry "
908c19800e8SDoug Rabson 			       "have consistency failure, length wrong");
909c19800e8SDoug Rabson 	return KADM5_BAD_DB;
910c19800e8SDoug Rabson     }
911b528cefcSMark Murray     return 0;
912c19800e8SDoug Rabson 
913c19800e8SDoug Rabson  end_of_storage:
914c19800e8SDoug Rabson     krb5_storage_seek(sp, oldoff, SEEK_SET);
915*ae771770SStanislav Sedov     krb5_set_error_message(context, ret, "kadm5_log_previous: end of storage "
916c19800e8SDoug Rabson 			   "reached before end");
917c19800e8SDoug Rabson     return ret;
918b528cefcSMark Murray }
919b528cefcSMark Murray 
920b528cefcSMark Murray /*
921b528cefcSMark Murray  * Replay a record from the log
922b528cefcSMark Murray  */
923b528cefcSMark Murray 
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,
927c19800e8SDoug Rabson 		  uint32_t ver,
928c19800e8SDoug Rabson 		  uint32_t len,
929b528cefcSMark Murray 		  krb5_storage *sp)
930b528cefcSMark Murray {
931b528cefcSMark Murray     switch (op) {
932b528cefcSMark Murray     case kadm_create :
933b528cefcSMark Murray 	return kadm5_log_replay_create (context, ver, len, sp);
934b528cefcSMark Murray     case kadm_delete :
935b528cefcSMark Murray 	return kadm5_log_replay_delete (context, ver, len, sp);
936b528cefcSMark Murray     case kadm_rename :
937b528cefcSMark Murray 	return kadm5_log_replay_rename (context, ver, len, sp);
938b528cefcSMark Murray     case kadm_modify :
939b528cefcSMark Murray 	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);
942b528cefcSMark Murray     default :
943*ae771770SStanislav Sedov 	krb5_set_error_message(context->context, KADM5_FAILURE,
944c19800e8SDoug Rabson 			       "Unsupported replay op %d", (int)op);
945b528cefcSMark Murray 	return KADM5_FAILURE;
946b528cefcSMark Murray     }
947b528cefcSMark Murray }
9485e9cd1aeSAssar Westerlund 
9495e9cd1aeSAssar Westerlund /*
9505e9cd1aeSAssar Westerlund  * 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;
957c19800e8SDoug Rabson     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);
9645e9cd1aeSAssar Westerlund     if (ret)
9655e9cd1aeSAssar Westerlund 	return ret;
9665e9cd1aeSAssar Westerlund 
9675e9cd1aeSAssar Westerlund     ret = kadm5_log_reinit (server_context);
9685e9cd1aeSAssar Westerlund     if (ret)
9695e9cd1aeSAssar Westerlund 	return ret;
9705e9cd1aeSAssar Westerlund 
971c19800e8SDoug Rabson     ret = kadm5_log_set_version (server_context, vno);
9725e9cd1aeSAssar Westerlund     if (ret)
9735e9cd1aeSAssar Westerlund 	return ret;
9745e9cd1aeSAssar Westerlund 
9755e9cd1aeSAssar Westerlund     ret = kadm5_log_nop (server_context);
9765e9cd1aeSAssar Westerlund     if (ret)
9775e9cd1aeSAssar Westerlund 	return ret;
9785e9cd1aeSAssar Westerlund 
9795e9cd1aeSAssar Westerlund     ret = kadm5_log_end (server_context);
9805e9cd1aeSAssar Westerlund     if (ret)
9815e9cd1aeSAssar Westerlund 	return ret;
9825e9cd1aeSAssar Westerlund     return 0;
9835e9cd1aeSAssar Westerlund 
9845e9cd1aeSAssar Westerlund }
985c19800e8SDoug Rabson 
986*ae771770SStanislav Sedov #ifndef NO_UNIX_SOCKETS
987*ae771770SStanislav Sedov 
988c19800e8SDoug Rabson static char *default_signal = NULL;
989c19800e8SDoug Rabson static HEIMDAL_MUTEX signal_mutex = HEIMDAL_MUTEX_INITIALIZER;
990c19800e8SDoug Rabson 
991c19800e8SDoug Rabson const char *
kadm5_log_signal_socket(krb5_context context)992c19800e8SDoug Rabson kadm5_log_signal_socket(krb5_context context)
993c19800e8SDoug Rabson {
994c19800e8SDoug Rabson     HEIMDAL_MUTEX_lock(&signal_mutex);
995c19800e8SDoug Rabson     if (!default_signal)
996c19800e8SDoug Rabson 	asprintf(&default_signal, "%s/signal", hdb_db_dir(context));
997c19800e8SDoug Rabson     HEIMDAL_MUTEX_unlock(&signal_mutex);
998c19800e8SDoug Rabson 
999c19800e8SDoug Rabson     return krb5_config_get_string_default(context,
1000c19800e8SDoug Rabson 					  NULL,
1001c19800e8SDoug Rabson 					  default_signal,
1002c19800e8SDoug Rabson 					  "kdc",
1003c19800e8SDoug Rabson 					  "signal_socket",
1004c19800e8SDoug Rabson 					  NULL);
1005c19800e8SDoug Rabson }
1006*ae771770SStanislav Sedov 
1007*ae771770SStanislav Sedov #else  /* NO_UNIX_SOCKETS */
1008*ae771770SStanislav Sedov 
1009*ae771770SStanislav Sedov #define SIGNAL_SOCKET_HOST "127.0.0.1"
1010*ae771770SStanislav Sedov #define SIGNAL_SOCKET_PORT "12701"
1011*ae771770SStanislav Sedov 
1012*ae771770SStanislav Sedov kadm5_ret_t
kadm5_log_signal_socket_info(krb5_context context,int server_end,struct addrinfo ** ret_addrs)1013*ae771770SStanislav Sedov kadm5_log_signal_socket_info(krb5_context context,
1014*ae771770SStanislav Sedov 			     int server_end,
1015*ae771770SStanislav Sedov 			     struct addrinfo **ret_addrs)
1016*ae771770SStanislav Sedov {
1017*ae771770SStanislav Sedov     struct addrinfo hints;
1018*ae771770SStanislav Sedov     struct addrinfo *addrs = NULL;
1019*ae771770SStanislav Sedov     kadm5_ret_t ret = KADM5_FAILURE;
1020*ae771770SStanislav Sedov     int wsret;
1021*ae771770SStanislav Sedov 
1022*ae771770SStanislav Sedov     memset(&hints, 0, sizeof(hints));
1023*ae771770SStanislav Sedov 
1024*ae771770SStanislav Sedov     hints.ai_flags = AI_NUMERICHOST;
1025*ae771770SStanislav Sedov     if (server_end)
1026*ae771770SStanislav Sedov 	hints.ai_flags |= AI_PASSIVE;
1027*ae771770SStanislav Sedov     hints.ai_family = AF_INET;
1028*ae771770SStanislav Sedov     hints.ai_socktype = SOCK_STREAM;
1029*ae771770SStanislav Sedov     hints.ai_protocol = IPPROTO_TCP;
1030*ae771770SStanislav Sedov 
1031*ae771770SStanislav Sedov     wsret = getaddrinfo(SIGNAL_SOCKET_HOST,
1032*ae771770SStanislav Sedov 			SIGNAL_SOCKET_PORT,
1033*ae771770SStanislav Sedov 			&hints, &addrs);
1034*ae771770SStanislav Sedov 
1035*ae771770SStanislav Sedov     if (wsret != 0) {
1036*ae771770SStanislav Sedov 	krb5_set_error_message(context, KADM5_FAILURE,
1037*ae771770SStanislav Sedov 			       "%s", gai_strerror(wsret));
1038*ae771770SStanislav Sedov 	goto done;
1039*ae771770SStanislav Sedov     }
1040*ae771770SStanislav Sedov 
1041*ae771770SStanislav Sedov     if (addrs == NULL) {
1042*ae771770SStanislav Sedov 	krb5_set_error_message(context, KADM5_FAILURE,
1043*ae771770SStanislav Sedov 			       "getaddrinfo() failed to return address list");
1044*ae771770SStanislav Sedov 	goto done;
1045*ae771770SStanislav Sedov     }
1046*ae771770SStanislav Sedov 
1047*ae771770SStanislav Sedov     *ret_addrs = addrs;
1048*ae771770SStanislav Sedov     addrs = NULL;
1049*ae771770SStanislav Sedov     ret = 0;
1050*ae771770SStanislav Sedov 
1051*ae771770SStanislav Sedov  done:
1052*ae771770SStanislav Sedov     if (addrs)
1053*ae771770SStanislav Sedov 	freeaddrinfo(addrs);
1054*ae771770SStanislav Sedov     return ret;
1055*ae771770SStanislav Sedov }
1056*ae771770SStanislav Sedov 
1057*ae771770SStanislav Sedov #endif
1058