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