xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/kadm5/iprop-log.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1*d3273b5bSchristos /*	$NetBSD: iprop-log.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
36ca1c9b0cSelric #include "iprop.h"
37ca1c9b0cSelric #include <krb5/sl.h>
38ca1c9b0cSelric #include <krb5/parse_time.h>
39ca1c9b0cSelric #include "iprop-commands.h"
40ca1c9b0cSelric 
41*d3273b5bSchristos __RCSID("$NetBSD: iprop-log.c,v 1.2 2017/01/28 21:31:49 christos Exp $");
42ca1c9b0cSelric 
43ca1c9b0cSelric static krb5_context context;
44ca1c9b0cSelric 
45ca1c9b0cSelric static kadm5_server_context *
get_kadmin_context(const char * config_file,char * realm)46ca1c9b0cSelric get_kadmin_context(const char *config_file, char *realm)
47ca1c9b0cSelric {
48ca1c9b0cSelric     kadm5_config_params conf;
49ca1c9b0cSelric     krb5_error_code ret;
50ca1c9b0cSelric     void *kadm_handle;
51b9d004c6Schristos     char *file = NULL;
52ca1c9b0cSelric     char **files;
53b9d004c6Schristos     int aret;
54ca1c9b0cSelric 
55ca1c9b0cSelric     if (config_file == NULL) {
56b9d004c6Schristos 	aret = asprintf(&file, "%s/kdc.conf", hdb_db_dir(context));
57b9d004c6Schristos 	if (aret == -1 || file == NULL)
58ca1c9b0cSelric 	    errx(1, "out of memory");
59ca1c9b0cSelric 	config_file = file;
60ca1c9b0cSelric     }
61ca1c9b0cSelric 
62ca1c9b0cSelric     ret = krb5_prepend_config_files_default(config_file, &files);
63b9d004c6Schristos     free(file);
64ca1c9b0cSelric     if (ret)
65ca1c9b0cSelric 	krb5_err(context, 1, ret, "getting configuration files");
66ca1c9b0cSelric 
67ca1c9b0cSelric     ret = krb5_set_config_files(context, files);
68ca1c9b0cSelric     krb5_free_config_files(files);
69ca1c9b0cSelric     if (ret)
70ca1c9b0cSelric 	krb5_err(context, 1, ret, "reading configuration files");
71ca1c9b0cSelric 
72ca1c9b0cSelric     memset(&conf, 0, sizeof(conf));
73ca1c9b0cSelric     if(realm) {
74ca1c9b0cSelric 	conf.mask |= KADM5_CONFIG_REALM;
75ca1c9b0cSelric 	conf.realm = realm;
76ca1c9b0cSelric     }
77ca1c9b0cSelric 
78ca1c9b0cSelric     ret = kadm5_init_with_password_ctx (context,
79ca1c9b0cSelric 					KADM5_ADMIN_SERVICE,
80ca1c9b0cSelric 					NULL,
81ca1c9b0cSelric 					KADM5_ADMIN_SERVICE,
82ca1c9b0cSelric 					&conf, 0, 0,
83ca1c9b0cSelric 					&kadm_handle);
84ca1c9b0cSelric     if (ret)
85ca1c9b0cSelric 	krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");
86ca1c9b0cSelric 
87ca1c9b0cSelric     return (kadm5_server_context *)kadm_handle;
88ca1c9b0cSelric }
89ca1c9b0cSelric 
90ca1c9b0cSelric /*
91ca1c9b0cSelric  * dump log
92ca1c9b0cSelric  */
93ca1c9b0cSelric 
94ca1c9b0cSelric static const char *op_names[] = {
95ca1c9b0cSelric     "get",
96ca1c9b0cSelric     "delete",
97ca1c9b0cSelric     "create",
98ca1c9b0cSelric     "rename",
99ca1c9b0cSelric     "chpass",
100ca1c9b0cSelric     "modify",
101ca1c9b0cSelric     "randkey",
102ca1c9b0cSelric     "get_privs",
103ca1c9b0cSelric     "get_princs",
104ca1c9b0cSelric     "chpass_with_key",
105ca1c9b0cSelric     "nop"
106ca1c9b0cSelric };
107ca1c9b0cSelric 
108b9d004c6Schristos static kadm5_ret_t
print_entry(kadm5_server_context * server_context,uint32_t ver,time_t timestamp,enum kadm_ops op,uint32_t len,krb5_storage * sp,void * ctx)109ca1c9b0cSelric print_entry(kadm5_server_context *server_context,
110ca1c9b0cSelric 	    uint32_t ver,
111ca1c9b0cSelric 	    time_t timestamp,
112ca1c9b0cSelric 	    enum kadm_ops op,
113ca1c9b0cSelric 	    uint32_t len,
114ca1c9b0cSelric 	    krb5_storage *sp,
115ca1c9b0cSelric 	    void *ctx)
116ca1c9b0cSelric {
117ca1c9b0cSelric     char t[256];
118b9d004c6Schristos     const char *entry_kind = ctx;
119ca1c9b0cSelric     int32_t mask;
120b9d004c6Schristos     int32_t nop_time;
121b9d004c6Schristos     uint32_t nop_ver;
122ca1c9b0cSelric     hdb_entry ent;
123ca1c9b0cSelric     krb5_principal source;
124ca1c9b0cSelric     char *name1, *name2;
125ca1c9b0cSelric     krb5_data data;
126ca1c9b0cSelric     krb5_context scontext = server_context->context;
127ca1c9b0cSelric     krb5_error_code ret;
128ca1c9b0cSelric 
129b9d004c6Schristos     krb5_data_zero(&data);
130b9d004c6Schristos 
131ca1c9b0cSelric     strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
132ca1c9b0cSelric 
1334f77a458Spettai     if((int)op < (int)kadm_get || (int)op > (int)kadm_nop) {
134ca1c9b0cSelric 	printf("unknown op: %d\n", op);
135b9d004c6Schristos 	return 0;
136ca1c9b0cSelric     }
137ca1c9b0cSelric 
138b9d004c6Schristos     printf ("%s%s: ver = %u, timestamp = %s, len = %u\n",
139b9d004c6Schristos 	    entry_kind, op_names[op], ver, t, len);
140ca1c9b0cSelric     switch(op) {
141ca1c9b0cSelric     case kadm_delete:
142ca1c9b0cSelric 	krb5_ret_principal(sp, &source);
143ca1c9b0cSelric 	krb5_unparse_name(scontext, source, &name1);
144ca1c9b0cSelric 	printf("    %s\n", name1);
145ca1c9b0cSelric 	free(name1);
146ca1c9b0cSelric 	krb5_free_principal(scontext, source);
147ca1c9b0cSelric 	break;
148ca1c9b0cSelric     case kadm_rename:
149ca1c9b0cSelric 	ret = krb5_data_alloc(&data, len);
150ca1c9b0cSelric 	if (ret)
151ca1c9b0cSelric 	    krb5_err (scontext, 1, ret, "kadm_rename: data alloc: %d", len);
152ca1c9b0cSelric 	krb5_ret_principal(sp, &source);
153ca1c9b0cSelric 	krb5_storage_read(sp, data.data, data.length);
154ca1c9b0cSelric 	hdb_value2entry(scontext, &data, &ent);
155ca1c9b0cSelric 	krb5_unparse_name(scontext, source, &name1);
156ca1c9b0cSelric 	krb5_unparse_name(scontext, ent.principal, &name2);
157ca1c9b0cSelric 	printf("    %s -> %s\n", name1, name2);
158ca1c9b0cSelric 	free(name1);
159ca1c9b0cSelric 	free(name2);
160ca1c9b0cSelric 	krb5_free_principal(scontext, source);
161ca1c9b0cSelric 	free_hdb_entry(&ent);
162ca1c9b0cSelric 	break;
163ca1c9b0cSelric     case kadm_create:
164ca1c9b0cSelric 	ret = krb5_data_alloc(&data, len);
165ca1c9b0cSelric 	if (ret)
166ca1c9b0cSelric 	    krb5_err (scontext, 1, ret, "kadm_create: data alloc: %d", len);
167ca1c9b0cSelric 	krb5_storage_read(sp, data.data, data.length);
168ca1c9b0cSelric 	ret = hdb_value2entry(scontext, &data, &ent);
169ca1c9b0cSelric 	if(ret)
170ca1c9b0cSelric 	    abort();
171ca1c9b0cSelric 	mask = ~0;
172ca1c9b0cSelric 	goto foo;
173ca1c9b0cSelric     case kadm_modify:
174ca1c9b0cSelric 	ret = krb5_data_alloc(&data, len);
175ca1c9b0cSelric 	if (ret)
176ca1c9b0cSelric 	    krb5_err (scontext, 1, ret, "kadm_modify: data alloc: %d", len);
177ca1c9b0cSelric 	krb5_ret_int32(sp, &mask);
178ca1c9b0cSelric 	krb5_storage_read(sp, data.data, data.length);
179ca1c9b0cSelric 	ret = hdb_value2entry(scontext, &data, &ent);
180ca1c9b0cSelric 	if(ret)
181ca1c9b0cSelric 	    abort();
182ca1c9b0cSelric     foo:
183ca1c9b0cSelric 	if(ent.principal /* mask & KADM5_PRINCIPAL */) {
184ca1c9b0cSelric 	    krb5_unparse_name(scontext, ent.principal, &name1);
185ca1c9b0cSelric 	    printf("    principal = %s\n", name1);
186ca1c9b0cSelric 	    free(name1);
187ca1c9b0cSelric 	}
188ca1c9b0cSelric 	if(mask & KADM5_PRINC_EXPIRE_TIME) {
189ca1c9b0cSelric 	    if(ent.valid_end == NULL) {
190ca1c9b0cSelric 		strlcpy(t, "never", sizeof(t));
191ca1c9b0cSelric 	    } else {
192ca1c9b0cSelric 		strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S",
193ca1c9b0cSelric 			 localtime(ent.valid_end));
194ca1c9b0cSelric 	    }
195ca1c9b0cSelric 	    printf("    expires = %s\n", t);
196ca1c9b0cSelric 	}
197ca1c9b0cSelric 	if(mask & KADM5_PW_EXPIRATION) {
198ca1c9b0cSelric 	    if(ent.pw_end == NULL) {
199ca1c9b0cSelric 		strlcpy(t, "never", sizeof(t));
200ca1c9b0cSelric 	    } else {
201ca1c9b0cSelric 		strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S",
202ca1c9b0cSelric 			 localtime(ent.pw_end));
203ca1c9b0cSelric 	    }
204ca1c9b0cSelric 	    printf("    password exp = %s\n", t);
205ca1c9b0cSelric 	}
206ca1c9b0cSelric 	if(mask & KADM5_LAST_PWD_CHANGE) {
207ca1c9b0cSelric 	}
208ca1c9b0cSelric 	if(mask & KADM5_ATTRIBUTES) {
209ca1c9b0cSelric 	    unparse_flags(HDBFlags2int(ent.flags),
210ca1c9b0cSelric 			  asn1_HDBFlags_units(), t, sizeof(t));
211ca1c9b0cSelric 	    printf("    attributes = %s\n", t);
212ca1c9b0cSelric 	}
213ca1c9b0cSelric 	if(mask & KADM5_MAX_LIFE) {
214ca1c9b0cSelric 	    if(ent.max_life == NULL)
215ca1c9b0cSelric 		strlcpy(t, "for ever", sizeof(t));
216ca1c9b0cSelric 	    else
217ca1c9b0cSelric 		unparse_time(*ent.max_life, t, sizeof(t));
218ca1c9b0cSelric 	    printf("    max life = %s\n", t);
219ca1c9b0cSelric 	}
220ca1c9b0cSelric 	if(mask & KADM5_MAX_RLIFE) {
221ca1c9b0cSelric 	    if(ent.max_renew == NULL)
222ca1c9b0cSelric 		strlcpy(t, "for ever", sizeof(t));
223ca1c9b0cSelric 	    else
224ca1c9b0cSelric 		unparse_time(*ent.max_renew, t, sizeof(t));
225ca1c9b0cSelric 	    printf("    max rlife = %s\n", t);
226ca1c9b0cSelric 	}
227ca1c9b0cSelric 	if(mask & KADM5_MOD_TIME) {
228ca1c9b0cSelric 	    printf("    mod time\n");
229ca1c9b0cSelric 	}
230ca1c9b0cSelric 	if(mask & KADM5_MOD_NAME) {
231ca1c9b0cSelric 	    printf("    mod name\n");
232ca1c9b0cSelric 	}
233ca1c9b0cSelric 	if(mask & KADM5_KVNO) {
234ca1c9b0cSelric 	    printf("    kvno = %d\n", ent.kvno);
235ca1c9b0cSelric 	}
236ca1c9b0cSelric 	if(mask & KADM5_MKVNO) {
237ca1c9b0cSelric 	    printf("    mkvno\n");
238ca1c9b0cSelric 	}
239ca1c9b0cSelric 	if(mask & KADM5_AUX_ATTRIBUTES) {
240ca1c9b0cSelric 	    printf("    aux attributes\n");
241ca1c9b0cSelric 	}
242ca1c9b0cSelric 	if(mask & KADM5_POLICY) {
243ca1c9b0cSelric 	    printf("    policy\n");
244ca1c9b0cSelric 	}
245ca1c9b0cSelric 	if(mask & KADM5_POLICY_CLR) {
246ca1c9b0cSelric 	    printf("    mod time\n");
247ca1c9b0cSelric 	}
248ca1c9b0cSelric 	if(mask & KADM5_LAST_SUCCESS) {
249ca1c9b0cSelric 	    printf("    last success\n");
250ca1c9b0cSelric 	}
251ca1c9b0cSelric 	if(mask & KADM5_LAST_FAILED) {
252ca1c9b0cSelric 	    printf("    last failed\n");
253ca1c9b0cSelric 	}
254ca1c9b0cSelric 	if(mask & KADM5_FAIL_AUTH_COUNT) {
255ca1c9b0cSelric 	    printf("    fail auth count\n");
256ca1c9b0cSelric 	}
257ca1c9b0cSelric 	if(mask & KADM5_KEY_DATA) {
258ca1c9b0cSelric 	    printf("    key data\n");
259ca1c9b0cSelric 	}
260ca1c9b0cSelric 	if(mask & KADM5_TL_DATA) {
261ca1c9b0cSelric 	    printf("    tl data\n");
262ca1c9b0cSelric 	}
263ca1c9b0cSelric 	free_hdb_entry(&ent);
264ca1c9b0cSelric 	break;
265ca1c9b0cSelric     case kadm_nop :
266b9d004c6Schristos         if (len == 16) {
267b9d004c6Schristos             uint64_t off;
268b9d004c6Schristos             krb5_ret_uint64(sp, &off);
269b9d004c6Schristos             printf("uberblock offset %llu ", (unsigned long long)off);
270b9d004c6Schristos         } else {
271b9d004c6Schristos             printf("nop");
272b9d004c6Schristos         }
273b9d004c6Schristos         if (len == 16 || len == 8) {
274b9d004c6Schristos             krb5_ret_int32(sp, &nop_time);
275b9d004c6Schristos             krb5_ret_uint32(sp, &nop_ver);
276b9d004c6Schristos 
277b9d004c6Schristos             timestamp = nop_time;
278b9d004c6Schristos             strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
279b9d004c6Schristos             printf("timestamp %s version %u", t, nop_ver);
280b9d004c6Schristos         }
281b9d004c6Schristos         printf("\n");
282ca1c9b0cSelric 	break;
283ca1c9b0cSelric     default:
284ca1c9b0cSelric 	abort();
285ca1c9b0cSelric     }
286b9d004c6Schristos     krb5_data_free(&data);
287b9d004c6Schristos 
288b9d004c6Schristos     return 0;
289ca1c9b0cSelric }
290ca1c9b0cSelric 
291ca1c9b0cSelric int
iprop_dump(struct dump_options * opt,int argc,char ** argv)292ca1c9b0cSelric iprop_dump(struct dump_options *opt, int argc, char **argv)
293ca1c9b0cSelric {
294ca1c9b0cSelric     kadm5_server_context *server_context;
295ca1c9b0cSelric     krb5_error_code ret;
296b9d004c6Schristos     enum kadm_iter_opts iter_opts_1st = 0;
297b9d004c6Schristos     enum kadm_iter_opts iter_opts_2nd = 0;
298b9d004c6Schristos     char *desc_1st = "";
299b9d004c6Schristos     char *desc_2nd = "";
300ca1c9b0cSelric 
301ca1c9b0cSelric     server_context = get_kadmin_context(opt->config_file_string,
302ca1c9b0cSelric 					opt->realm_string);
303ca1c9b0cSelric 
304b9d004c6Schristos     if (argc > 0) {
305b9d004c6Schristos         free(server_context->log_context.log_file);
306b9d004c6Schristos         server_context->log_context.log_file = strdup(argv[0]);
307b9d004c6Schristos         if (server_context->log_context.log_file == NULL)
308b9d004c6Schristos             krb5_err(context, 1, errno, "strdup");
309b9d004c6Schristos     }
310ca1c9b0cSelric 
311b9d004c6Schristos     if (opt->reverse_flag) {
312b9d004c6Schristos         iter_opts_1st = kadm_backward | kadm_unconfirmed;
313b9d004c6Schristos         iter_opts_2nd = kadm_backward | kadm_confirmed;
314b9d004c6Schristos         desc_1st = "unconfirmed ";
315b9d004c6Schristos     } else {
316b9d004c6Schristos         iter_opts_1st = kadm_forward | kadm_confirmed;
317b9d004c6Schristos         iter_opts_2nd = kadm_forward | kadm_unconfirmed;
318b9d004c6Schristos         desc_2nd = "unconfirmed";
319b9d004c6Schristos     }
320b9d004c6Schristos 
321b9d004c6Schristos     if (opt->no_lock_flag) {
322b9d004c6Schristos         ret = kadm5_log_init_sharedlock(server_context, LOCK_NB);
323b9d004c6Schristos         if (ret == EAGAIN || ret == EWOULDBLOCK) {
324b9d004c6Schristos             warnx("Not locking the iprop log");
325b9d004c6Schristos             ret = kadm5_log_init_nolock(server_context);
326b9d004c6Schristos             if (ret)
327b9d004c6Schristos                 krb5_err(context, 1, ret, "kadm5_log_init_nolock");
328b9d004c6Schristos         }
329b9d004c6Schristos     } else {
330b9d004c6Schristos         warnx("If this command appears to block, try the --no-lock option");
331b9d004c6Schristos         ret = kadm5_log_init_sharedlock(server_context, 0);
332b9d004c6Schristos         if (ret)
333b9d004c6Schristos             krb5_err(context, 1, ret, "kadm5_log_init_sharedlock");
334b9d004c6Schristos     }
335b9d004c6Schristos 
336b9d004c6Schristos     ret = kadm5_log_foreach(server_context, iter_opts_1st,
337b9d004c6Schristos                             NULL, print_entry, desc_1st);
338b9d004c6Schristos     if (ret)
339b9d004c6Schristos 	krb5_warn(context, ret, "kadm5_log_foreach");
340b9d004c6Schristos 
341b9d004c6Schristos     ret = kadm5_log_foreach(server_context, iter_opts_2nd,
342b9d004c6Schristos                             NULL, print_entry, desc_2nd);
343ca1c9b0cSelric     if (ret)
344ca1c9b0cSelric 	krb5_warn(context, ret, "kadm5_log_foreach");
345ca1c9b0cSelric 
346ca1c9b0cSelric     ret = kadm5_log_end (server_context);
347ca1c9b0cSelric     if (ret)
348ca1c9b0cSelric 	krb5_warn(context, ret, "kadm5_log_end");
349b9d004c6Schristos 
350b9d004c6Schristos     kadm5_destroy(server_context);
351ca1c9b0cSelric     return 0;
352ca1c9b0cSelric }
353ca1c9b0cSelric 
354ca1c9b0cSelric int
iprop_truncate(struct truncate_options * opt,int argc,char ** argv)355ca1c9b0cSelric iprop_truncate(struct truncate_options *opt, int argc, char **argv)
356ca1c9b0cSelric {
357ca1c9b0cSelric     kadm5_server_context *server_context;
358ca1c9b0cSelric     krb5_error_code ret;
359ca1c9b0cSelric 
360ca1c9b0cSelric     server_context = get_kadmin_context(opt->config_file_string,
361ca1c9b0cSelric 					opt->realm_string);
362ca1c9b0cSelric 
363b9d004c6Schristos     if (argc > 0) {
364b9d004c6Schristos         free(server_context->log_context.log_file);
365b9d004c6Schristos         server_context->log_context.log_file = strdup(argv[0]);
366b9d004c6Schristos         if (server_context->log_context.log_file == NULL)
367b9d004c6Schristos             krb5_err(context, 1, errno, "strdup");
368b9d004c6Schristos     }
369b9d004c6Schristos 
370b9d004c6Schristos     if (opt->keep_entries_integer < 0 &&
371b9d004c6Schristos         opt->max_bytes_integer < 0) {
372b9d004c6Schristos         opt->keep_entries_integer = 100;
373b9d004c6Schristos         opt->max_bytes_integer = 0;
374b9d004c6Schristos     }
375b9d004c6Schristos     if (opt->keep_entries_integer < 0)
376b9d004c6Schristos         opt->keep_entries_integer = 0;
377b9d004c6Schristos     if (opt->max_bytes_integer < 0)
378b9d004c6Schristos         opt->max_bytes_integer = 0;
379b9d004c6Schristos 
380b9d004c6Schristos     if (opt->reset_flag) {
381b9d004c6Schristos         /* First recover unconfirmed records */
382b9d004c6Schristos         ret = kadm5_log_init(server_context);
383b9d004c6Schristos         if (ret == 0)
384b9d004c6Schristos             ret = kadm5_log_reinit(server_context, 0);
385b9d004c6Schristos     } else {
386b9d004c6Schristos         ret = kadm5_log_init(server_context);
387b9d004c6Schristos         if (ret)
388b9d004c6Schristos             krb5_err(context, 1, ret, "kadm5_log_init");
389b9d004c6Schristos         ret = kadm5_log_truncate(server_context, opt->keep_entries_integer,
390b9d004c6Schristos                                  opt->max_bytes_integer);
391b9d004c6Schristos     }
392ca1c9b0cSelric     if (ret)
393ca1c9b0cSelric 	krb5_err(context, 1, ret, "kadm5_log_truncate");
394ca1c9b0cSelric 
395b9d004c6Schristos     kadm5_log_signal_master(server_context);
396b9d004c6Schristos 
397b9d004c6Schristos     kadm5_destroy(server_context);
398ca1c9b0cSelric     return 0;
399ca1c9b0cSelric }
400ca1c9b0cSelric 
401ca1c9b0cSelric int
last_version(struct last_version_options * opt,int argc,char ** argv)402ca1c9b0cSelric last_version(struct last_version_options *opt, int argc, char **argv)
403ca1c9b0cSelric {
404ca1c9b0cSelric     kadm5_server_context *server_context;
405b9d004c6Schristos     char *alt_argv[2] = { NULL, NULL };
406ca1c9b0cSelric     krb5_error_code ret;
407ca1c9b0cSelric     uint32_t version;
408b9d004c6Schristos     size_t i;
409ca1c9b0cSelric 
410ca1c9b0cSelric     server_context = get_kadmin_context(opt->config_file_string,
411ca1c9b0cSelric 					opt->realm_string);
412ca1c9b0cSelric 
413b9d004c6Schristos     if (argc == 0) {
414b9d004c6Schristos         alt_argv[0] = strdup(server_context->log_context.log_file);
415b9d004c6Schristos         if (alt_argv[0] == NULL)
416b9d004c6Schristos             krb5_err(context, 1, errno, "strdup");
417b9d004c6Schristos         argv = alt_argv;
418b9d004c6Schristos         argc = 1;
419b9d004c6Schristos     }
420b9d004c6Schristos 
421b9d004c6Schristos     for (i = 0; i < argc; i++) {
422b9d004c6Schristos         free(server_context->log_context.log_file);
423b9d004c6Schristos         server_context->log_context.log_file = strdup(argv[i]);
424b9d004c6Schristos         if (server_context->log_context.log_file == NULL)
425b9d004c6Schristos             krb5_err(context, 1, errno, "strdup");
426b9d004c6Schristos 
427b9d004c6Schristos         if (opt->no_lock_flag) {
428b9d004c6Schristos             ret = kadm5_log_init_sharedlock(server_context, LOCK_NB);
429b9d004c6Schristos             if (ret == EAGAIN || ret == EWOULDBLOCK) {
430b9d004c6Schristos                 warnx("Not locking the iprop log");
431b9d004c6Schristos                 ret = kadm5_log_init_nolock(server_context);
432ca1c9b0cSelric                 if (ret)
433b9d004c6Schristos                     krb5_err(context, 1, ret, "kadm5_log_init_nolock");
434b9d004c6Schristos             }
435b9d004c6Schristos         } else {
436b9d004c6Schristos             warnx("If this command appears to block, try the "
437b9d004c6Schristos                   "--no-lock option");
438b9d004c6Schristos             ret = kadm5_log_init_sharedlock(server_context, 0);
439b9d004c6Schristos             if (ret)
440b9d004c6Schristos                 krb5_err(context, 1, ret, "kadm5_log_init_sharedlock");
441b9d004c6Schristos         }
442ca1c9b0cSelric 
443ca1c9b0cSelric         ret = kadm5_log_get_version (server_context, &version);
444ca1c9b0cSelric         if (ret)
445ca1c9b0cSelric             krb5_err (context, 1, ret, "kadm5_log_get_version");
446ca1c9b0cSelric 
447ca1c9b0cSelric         ret = kadm5_log_end (server_context);
448ca1c9b0cSelric         if (ret)
449ca1c9b0cSelric             krb5_warn(context, ret, "kadm5_log_end");
450ca1c9b0cSelric 
451ca1c9b0cSelric         printf("version: %lu\n", (unsigned long)version);
452b9d004c6Schristos     }
453ca1c9b0cSelric 
454b9d004c6Schristos     kadm5_destroy(server_context);
455b9d004c6Schristos     free(alt_argv[0]);
456b9d004c6Schristos     return 0;
457b9d004c6Schristos }
458b9d004c6Schristos 
459b9d004c6Schristos int
signal_master(struct signal_options * opt,int argc,char ** argv)460b9d004c6Schristos signal_master(struct signal_options *opt, int argc, char **argv)
461b9d004c6Schristos {
462b9d004c6Schristos     kadm5_server_context *server_context;
463b9d004c6Schristos 
464b9d004c6Schristos     server_context = get_kadmin_context(opt->config_file_string,
465b9d004c6Schristos 					opt->realm_string);
466b9d004c6Schristos 
467b9d004c6Schristos     kadm5_log_signal_master(server_context);
468b9d004c6Schristos 
469b9d004c6Schristos     kadm5_destroy(server_context);
470ca1c9b0cSelric     return 0;
471ca1c9b0cSelric }
472ca1c9b0cSelric 
473ca1c9b0cSelric /*
474ca1c9b0cSelric  * Replay log
475ca1c9b0cSelric  */
476ca1c9b0cSelric 
477ca1c9b0cSelric int start_version = -1;
478ca1c9b0cSelric int end_version = -1;
479ca1c9b0cSelric 
480b9d004c6Schristos static kadm5_ret_t
apply_entry(kadm5_server_context * server_context,uint32_t ver,time_t timestamp,enum kadm_ops op,uint32_t len,krb5_storage * sp,void * ctx)481ca1c9b0cSelric apply_entry(kadm5_server_context *server_context,
482ca1c9b0cSelric 	    uint32_t ver,
483ca1c9b0cSelric 	    time_t timestamp,
484ca1c9b0cSelric 	    enum kadm_ops op,
485ca1c9b0cSelric 	    uint32_t len,
486ca1c9b0cSelric 	    krb5_storage *sp,
487ca1c9b0cSelric 	    void *ctx)
488ca1c9b0cSelric {
489ca1c9b0cSelric     struct replay_options *opt = ctx;
490ca1c9b0cSelric     krb5_error_code ret;
491ca1c9b0cSelric 
4924f77a458Spettai     if((opt->start_version_integer != -1 && ver < (uint32_t)opt->start_version_integer) ||
4934f77a458Spettai        (opt->end_version_integer != -1 && ver > (uint32_t)opt->end_version_integer)) {
494ca1c9b0cSelric 	/* XXX skip this entry */
495b9d004c6Schristos 	return 0;
496ca1c9b0cSelric     }
497ca1c9b0cSelric     printf ("ver %u... ", ver);
498ca1c9b0cSelric     fflush (stdout);
499ca1c9b0cSelric 
500b9d004c6Schristos     ret = kadm5_log_replay(server_context, op, ver, len, sp);
501ca1c9b0cSelric     if (ret)
502ca1c9b0cSelric 	krb5_warn (server_context->context, ret, "kadm5_log_replay");
503ca1c9b0cSelric 
504ca1c9b0cSelric     printf ("done\n");
505b9d004c6Schristos 
506b9d004c6Schristos     return 0;
507ca1c9b0cSelric }
508ca1c9b0cSelric 
509ca1c9b0cSelric int
iprop_replay(struct replay_options * opt,int argc,char ** argv)510ca1c9b0cSelric iprop_replay(struct replay_options *opt, int argc, char **argv)
511ca1c9b0cSelric {
512ca1c9b0cSelric     kadm5_server_context *server_context;
513ca1c9b0cSelric     krb5_error_code ret;
514ca1c9b0cSelric 
515ca1c9b0cSelric     server_context = get_kadmin_context(opt->config_file_string,
516ca1c9b0cSelric 					opt->realm_string);
517ca1c9b0cSelric 
518b9d004c6Schristos     if (argc > 0) {
519b9d004c6Schristos         free(server_context->log_context.log_file);
520b9d004c6Schristos         server_context->log_context.log_file = strdup(argv[0]);
521b9d004c6Schristos         if (server_context->log_context.log_file == NULL)
522b9d004c6Schristos             krb5_err(context, 1, errno, "strdup");
523b9d004c6Schristos     }
524b9d004c6Schristos 
525ca1c9b0cSelric     ret = server_context->db->hdb_open(context,
526ca1c9b0cSelric 				       server_context->db,
527ca1c9b0cSelric 				       O_RDWR | O_CREAT, 0600);
528ca1c9b0cSelric     if (ret)
529ca1c9b0cSelric 	krb5_err (context, 1, ret, "db->open");
530ca1c9b0cSelric 
531ca1c9b0cSelric     ret = kadm5_log_init (server_context);
532ca1c9b0cSelric     if (ret)
533ca1c9b0cSelric 	krb5_err (context, 1, ret, "kadm5_log_init");
534ca1c9b0cSelric 
535b9d004c6Schristos     ret = kadm5_log_foreach(server_context,
536b9d004c6Schristos                             kadm_forward | kadm_confirmed | kadm_unconfirmed,
537b9d004c6Schristos                             NULL, apply_entry, opt);
538ca1c9b0cSelric     if(ret)
539ca1c9b0cSelric 	krb5_warn(context, ret, "kadm5_log_foreach");
540ca1c9b0cSelric     ret = kadm5_log_end (server_context);
541ca1c9b0cSelric     if (ret)
542ca1c9b0cSelric 	krb5_warn(context, ret, "kadm5_log_end");
543ca1c9b0cSelric     ret = server_context->db->hdb_close (context, server_context->db);
544ca1c9b0cSelric     if (ret)
545ca1c9b0cSelric 	krb5_err (context, 1, ret, "db->close");
546ca1c9b0cSelric 
547b9d004c6Schristos     kadm5_destroy(server_context);
548ca1c9b0cSelric     return 0;
549ca1c9b0cSelric }
550ca1c9b0cSelric 
551ca1c9b0cSelric static int help_flag;
552ca1c9b0cSelric static int version_flag;
553ca1c9b0cSelric 
554ca1c9b0cSelric static struct getargs args[] = {
555ca1c9b0cSelric     { "version", 	0,	arg_flag, 	&version_flag,
556ca1c9b0cSelric       NULL,		NULL
557ca1c9b0cSelric     },
558ca1c9b0cSelric     { "help", 	'h', 	arg_flag, 	&help_flag,
559ca1c9b0cSelric       NULL, NULL
560ca1c9b0cSelric     }
561ca1c9b0cSelric };
562ca1c9b0cSelric 
563ca1c9b0cSelric static int num_args = sizeof(args) / sizeof(args[0]);
564ca1c9b0cSelric 
565ca1c9b0cSelric int
help(void * opt,int argc,char ** argv)566ca1c9b0cSelric help(void *opt, int argc, char **argv)
567ca1c9b0cSelric {
568ca1c9b0cSelric     if(argc == 0) {
569ca1c9b0cSelric 	sl_help(commands, 1, argv - 1 /* XXX */);
570ca1c9b0cSelric     } else {
571ca1c9b0cSelric 	SL_cmd *c = sl_match (commands, argv[0], 0);
572ca1c9b0cSelric  	if(c == NULL) {
573ca1c9b0cSelric 	    fprintf (stderr, "No such command: %s. "
574ca1c9b0cSelric 		     "Try \"help\" for a list of commands\n",
575ca1c9b0cSelric 		     argv[0]);
576ca1c9b0cSelric 	} else {
577ca1c9b0cSelric 	    if(c->func) {
5784f77a458Spettai 		static char shelp[] = "--help";
5794f77a458Spettai 		char *fake[3];
580ca1c9b0cSelric 		fake[0] = argv[0];
5814f77a458Spettai 		fake[1] = shelp;
5824f77a458Spettai 		fake[2] = NULL;
583ca1c9b0cSelric 		(*c->func)(2, fake);
584ca1c9b0cSelric 		fprintf(stderr, "\n");
585ca1c9b0cSelric 	    }
586ca1c9b0cSelric 	    if(c->help && *c->help)
587ca1c9b0cSelric 		fprintf (stderr, "%s\n", c->help);
588ca1c9b0cSelric 	    if((++c)->name && c->func == NULL) {
589ca1c9b0cSelric 		int f = 0;
590ca1c9b0cSelric 		fprintf (stderr, "Synonyms:");
591ca1c9b0cSelric 		while (c->name && c->func == NULL) {
592ca1c9b0cSelric 		    fprintf (stderr, "%s%s", f ? ", " : " ", (c++)->name);
593ca1c9b0cSelric 		    f = 1;
594ca1c9b0cSelric 		}
595ca1c9b0cSelric 		fprintf (stderr, "\n");
596ca1c9b0cSelric 	    }
597ca1c9b0cSelric 	}
598ca1c9b0cSelric     }
599ca1c9b0cSelric     return 0;
600ca1c9b0cSelric }
601ca1c9b0cSelric 
602ca1c9b0cSelric static void
usage(int status)603ca1c9b0cSelric usage(int status)
604ca1c9b0cSelric {
605ca1c9b0cSelric     arg_printusage(args, num_args, NULL, "command");
606ca1c9b0cSelric     exit(status);
607ca1c9b0cSelric }
608ca1c9b0cSelric 
609ca1c9b0cSelric int
main(int argc,char ** argv)610ca1c9b0cSelric main(int argc, char **argv)
611ca1c9b0cSelric {
612ca1c9b0cSelric     int optidx = 0;
613ca1c9b0cSelric     krb5_error_code ret;
614ca1c9b0cSelric 
615ca1c9b0cSelric     setprogname(argv[0]);
616ca1c9b0cSelric 
617ca1c9b0cSelric     if(getarg(args, num_args, argc, argv, &optidx))
618ca1c9b0cSelric 	usage(1);
619ca1c9b0cSelric     if(help_flag)
620ca1c9b0cSelric 	usage(0);
621ca1c9b0cSelric     if(version_flag) {
622ca1c9b0cSelric 	print_version(NULL);
623ca1c9b0cSelric 	exit(0);
624ca1c9b0cSelric     }
625ca1c9b0cSelric     argc -= optidx;
626ca1c9b0cSelric     argv += optidx;
627ca1c9b0cSelric     if(argc == 0)
628ca1c9b0cSelric 	usage(1);
629ca1c9b0cSelric 
630ca1c9b0cSelric     ret = krb5_init_context(&context);
631ca1c9b0cSelric     if (ret)
632ca1c9b0cSelric 	errx(1, "krb5_init_context failed with: %d\n", ret);
633ca1c9b0cSelric 
634ca1c9b0cSelric     ret = sl_command(commands, argc, argv);
635ca1c9b0cSelric     if(ret == -1)
636ca1c9b0cSelric 	warnx ("unrecognized command: %s", argv[0]);
637ca1c9b0cSelric     return ret;
638ca1c9b0cSelric }
639