xref: /minix3/crypto/external/bsd/heimdal/dist/lib/kadm5/log.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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, &timestamp);
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