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