2 * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <parse_time.h>
37 #include "iprop-commands.h"
41 static krb5_context context
;
43 static kadm5_server_context
*
44 get_kadmin_context(const char *config_file
, char *realm
)
46 kadm5_config_params conf
;
53 if (config_file
== NULL
) {
54 aret
= asprintf(&file
, "%s/kdc.conf", hdb_db_dir(context
));
55 if (aret
== -1 || file
== NULL
)
56 errx(1, "out of memory");
60 ret
= krb5_prepend_config_files_default(config_file
, &files
);
63 krb5_err(context
, 1, ret
, "getting configuration files");
65 ret
= krb5_set_config_files(context
, files
);
66 krb5_free_config_files(files
);
68 krb5_err(context
, 1, ret
, "reading configuration files");
70 memset(&conf
, 0, sizeof(conf
));
72 conf
.mask
|= KADM5_CONFIG_REALM
;
76 ret
= kadm5_init_with_password_ctx (context
,
83 krb5_err (context
, 1, ret
, "kadm5_init_with_password_ctx");
85 return (kadm5_server_context
*)kadm_handle
;
92 static const char *op_names
[] = {
107 print_entry(kadm5_server_context
*server_context
,
116 const char *entry_kind
= ctx
;
121 krb5_principal source
;
124 krb5_context scontext
= server_context
->context
;
127 krb5_data_zero(&data
);
129 strftime(t
, sizeof(t
), "%Y-%m-%d %H:%M:%S", localtime(×tamp
));
131 if((int)op
< (int)kadm_get
|| (int)op
> (int)kadm_nop
) {
132 printf("unknown op: %d\n", op
);
136 printf ("%s%s: ver = %u, timestamp = %s, len = %u\n",
137 entry_kind
, op_names
[op
], ver
, t
, len
);
140 ret
= krb5_ret_principal(sp
, &source
);
142 ret
= krb5_unparse_name(scontext
, source
, &name1
);
144 krb5_err(scontext
, 1, ret
, "Failed to read a delete record");
145 printf(" %s\n", name1
);
147 krb5_free_principal(scontext
, source
);
150 ret
= krb5_data_alloc(&data
, len
);
152 ret
= krb5_ret_principal(sp
, &source
);
153 if (ret
== 0 && krb5_storage_read(sp
, data
.data
, data
.length
) == -1)
156 ret
= hdb_value2entry(scontext
, &data
, &ent
);
158 ret
= krb5_unparse_name(scontext
, source
, &name1
);
160 ret
= krb5_unparse_name(scontext
, ent
.principal
, &name2
);
162 krb5_err(scontext
, 1, ret
, "Failed to read a rename record");
163 printf(" %s -> %s\n", name1
, name2
);
166 krb5_free_principal(scontext
, source
);
167 free_hdb_entry(&ent
);
170 ret
= krb5_data_alloc(&data
, len
);
171 if (ret
== 0 && krb5_storage_read(sp
, data
.data
, data
.length
) == -1)
174 ret
= hdb_value2entry(scontext
, &data
, &ent
);
176 krb5_err(scontext
, 1, ret
, "Failed to read a create record");
180 ret
= krb5_data_alloc(&data
, len
);
182 ret
= krb5_ret_int32(sp
, &mask
);
183 if (ret
== 0 && krb5_storage_read(sp
, data
.data
, data
.length
) == -1)
186 ret
= hdb_value2entry(scontext
, &data
, &ent
);
188 krb5_err(scontext
, 1, ret
, "Failed to read a modify record");
190 if(ent
.principal
/* mask & KADM5_PRINCIPAL */) {
191 ret
= krb5_unparse_name(scontext
, ent
.principal
, &name1
);
193 krb5_err(scontext
, 1, ret
,
194 "Failed to process a create or modify record");
195 printf(" principal = %s\n", name1
);
198 if(mask
& KADM5_PRINC_EXPIRE_TIME
) {
199 if(ent
.valid_end
== NULL
) {
200 strlcpy(t
, "never", sizeof(t
));
202 strftime(t
, sizeof(t
), "%Y-%m-%d %H:%M:%S",
203 localtime(ent
.valid_end
));
205 printf(" expires = %s\n", t
);
207 if(mask
& KADM5_PW_EXPIRATION
) {
208 if(ent
.pw_end
== NULL
) {
209 strlcpy(t
, "never", sizeof(t
));
211 strftime(t
, sizeof(t
), "%Y-%m-%d %H:%M:%S",
212 localtime(ent
.pw_end
));
214 printf(" password exp = %s\n", t
);
216 if(mask
& KADM5_LAST_PWD_CHANGE
) {
218 if(mask
& KADM5_ATTRIBUTES
) {
219 unparse_flags(HDBFlags2int(ent
.flags
),
220 asn1_HDBFlags_units(), t
, sizeof(t
));
221 printf(" attributes = %s\n", t
);
223 if(mask
& KADM5_MAX_LIFE
) {
224 if(ent
.max_life
== NULL
)
225 strlcpy(t
, "for ever", sizeof(t
));
227 unparse_time(*ent
.max_life
, t
, sizeof(t
));
228 printf(" max life = %s\n", t
);
230 if(mask
& KADM5_MAX_RLIFE
) {
231 if(ent
.max_renew
== NULL
)
232 strlcpy(t
, "for ever", sizeof(t
));
234 unparse_time(*ent
.max_renew
, t
, sizeof(t
));
235 printf(" max rlife = %s\n", t
);
237 if(mask
& KADM5_MOD_TIME
) {
238 printf(" mod time\n");
240 if(mask
& KADM5_MOD_NAME
) {
241 printf(" mod name\n");
243 if(mask
& KADM5_KVNO
) {
244 printf(" kvno = %d\n", ent
.kvno
);
246 if(mask
& KADM5_MKVNO
) {
249 if(mask
& KADM5_AUX_ATTRIBUTES
) {
250 printf(" aux attributes\n");
252 if(mask
& KADM5_POLICY
) {
255 if(mask
& KADM5_POLICY_CLR
) {
256 printf(" mod time\n");
258 if(mask
& KADM5_LAST_SUCCESS
) {
259 printf(" last success\n");
261 if(mask
& KADM5_LAST_FAILED
) {
262 printf(" last failed\n");
264 if(mask
& KADM5_FAIL_AUTH_COUNT
) {
265 printf(" fail auth count\n");
267 if(mask
& KADM5_KEY_DATA
) {
268 printf(" key data\n");
270 if(mask
& KADM5_TL_DATA
) {
271 printf(" tl data\n");
273 free_hdb_entry(&ent
);
278 ret
= krb5_ret_uint64(sp
, &off
);
280 krb5_err(scontext
, 1, ret
, "Failed to read a no-op record");
281 printf("uberblock offset %llu ", (unsigned long long)off
);
285 if (len
== 16 || len
== 8) {
286 ret
= krb5_ret_int32(sp
, &nop_time
);
288 ret
= krb5_ret_uint32(sp
, &nop_ver
);
290 krb5_err(scontext
, 1, ret
, "Failed to read a no-op record");
292 timestamp
= nop_time
;
293 strftime(t
, sizeof(t
), "%Y-%m-%d %H:%M:%S", localtime(×tamp
));
294 printf("timestamp %s version %u", t
, nop_ver
);
299 krb5_errx(scontext
, 1, "Unknown record type");
301 krb5_data_free(&data
);
307 iprop_dump(struct dump_options
*opt
, int argc
, char **argv
)
309 kadm5_server_context
*server_context
;
311 enum kadm_iter_opts iter_opts_1st
= 0;
312 enum kadm_iter_opts iter_opts_2nd
= 0;
316 server_context
= get_kadmin_context(opt
->config_file_string
,
320 free(server_context
->log_context
.log_file
);
321 server_context
->log_context
.log_file
= strdup(argv
[0]);
322 if (server_context
->log_context
.log_file
== NULL
)
323 krb5_err(context
, 1, errno
, "strdup");
326 if (opt
->reverse_flag
) {
327 iter_opts_1st
= kadm_backward
| kadm_unconfirmed
;
328 iter_opts_2nd
= kadm_backward
| kadm_confirmed
;
329 desc_1st
= "unconfirmed ";
331 iter_opts_1st
= kadm_forward
| kadm_confirmed
;
332 iter_opts_2nd
= kadm_forward
| kadm_unconfirmed
;
333 desc_2nd
= "unconfirmed";
336 if (opt
->no_lock_flag
) {
337 ret
= kadm5_log_init_sharedlock(server_context
, LOCK_NB
);
338 if (ret
== EAGAIN
|| ret
== EWOULDBLOCK
) {
339 warnx("Not locking the iprop log");
340 ret
= kadm5_log_init_nolock(server_context
);
342 krb5_err(context
, 1, ret
, "kadm5_log_init_nolock");
345 warnx("If this command appears to block, try the --no-lock option");
346 ret
= kadm5_log_init_sharedlock(server_context
, 0);
348 krb5_err(context
, 1, ret
, "kadm5_log_init_sharedlock");
351 ret
= kadm5_log_foreach(server_context
, iter_opts_1st
,
352 NULL
, print_entry
, desc_1st
);
354 krb5_warn(context
, ret
, "kadm5_log_foreach");
356 ret
= kadm5_log_foreach(server_context
, iter_opts_2nd
,
357 NULL
, print_entry
, desc_2nd
);
359 krb5_warn(context
, ret
, "kadm5_log_foreach");
361 ret
= kadm5_log_end (server_context
);
363 krb5_warn(context
, ret
, "kadm5_log_end");
365 kadm5_destroy(server_context
);
370 iprop_truncate(struct truncate_options
*opt
, int argc
, char **argv
)
372 kadm5_server_context
*server_context
;
375 server_context
= get_kadmin_context(opt
->config_file_string
,
379 free(server_context
->log_context
.log_file
);
380 server_context
->log_context
.log_file
= strdup(argv
[0]);
381 if (server_context
->log_context
.log_file
== NULL
)
382 krb5_err(context
, 1, errno
, "strdup");
385 if (opt
->keep_entries_integer
< 0 &&
386 opt
->max_bytes_integer
< 0) {
387 opt
->keep_entries_integer
= 100;
388 opt
->max_bytes_integer
= 0;
390 if (opt
->keep_entries_integer
< 0)
391 opt
->keep_entries_integer
= 0;
392 if (opt
->max_bytes_integer
< 0)
393 opt
->max_bytes_integer
= 0;
395 if (opt
->reset_flag
) {
396 /* First recover unconfirmed records */
397 ret
= kadm5_log_init(server_context
);
399 ret
= kadm5_log_reinit(server_context
, 0);
401 ret
= kadm5_log_init(server_context
);
403 krb5_err(context
, 1, ret
, "kadm5_log_init");
404 ret
= kadm5_log_truncate(server_context
, opt
->keep_entries_integer
,
405 opt
->max_bytes_integer
);
408 krb5_err(context
, 1, ret
, "kadm5_log_truncate");
410 kadm5_log_signal_master(server_context
);
412 kadm5_destroy(server_context
);
417 last_version(struct last_version_options
*opt
, int argc
, char **argv
)
419 kadm5_server_context
*server_context
;
420 char *alt_argv
[2] = { NULL
, NULL
};
425 server_context
= get_kadmin_context(opt
->config_file_string
,
429 alt_argv
[0] = strdup(server_context
->log_context
.log_file
);
430 if (alt_argv
[0] == NULL
)
431 krb5_err(context
, 1, errno
, "strdup");
436 for (i
= 0; i
< argc
; i
++) {
437 free(server_context
->log_context
.log_file
);
438 server_context
->log_context
.log_file
= strdup(argv
[i
]);
439 if (server_context
->log_context
.log_file
== NULL
)
440 krb5_err(context
, 1, errno
, "strdup");
442 if (opt
->no_lock_flag
) {
443 ret
= kadm5_log_init_sharedlock(server_context
, LOCK_NB
);
444 if (ret
== EAGAIN
|| ret
== EWOULDBLOCK
) {
445 warnx("Not locking the iprop log");
446 ret
= kadm5_log_init_nolock(server_context
);
448 krb5_err(context
, 1, ret
, "kadm5_log_init_nolock");
451 warnx("If this command appears to block, try the "
453 ret
= kadm5_log_init_sharedlock(server_context
, 0);
455 krb5_err(context
, 1, ret
, "kadm5_log_init_sharedlock");
458 ret
= kadm5_log_get_version (server_context
, &version
);
460 krb5_err (context
, 1, ret
, "kadm5_log_get_version");
462 ret
= kadm5_log_end (server_context
);
464 krb5_warn(context
, ret
, "kadm5_log_end");
466 printf("version: %lu\n", (unsigned long)version
);
469 kadm5_destroy(server_context
);
475 signal_master(struct signal_options
*opt
, int argc
, char **argv
)
477 kadm5_server_context
*server_context
;
479 server_context
= get_kadmin_context(opt
->config_file_string
,
482 kadm5_log_signal_master(server_context
);
484 kadm5_destroy(server_context
);
492 int start_version
= -1;
493 int end_version
= -1;
496 apply_entry(kadm5_server_context
*server_context
,
504 struct replay_options
*opt
= ctx
;
507 if((opt
->start_version_integer
!= -1 && ver
< (uint32_t)opt
->start_version_integer
) ||
508 (opt
->end_version_integer
!= -1 && ver
> (uint32_t)opt
->end_version_integer
)) {
509 /* XXX skip this entry */
512 printf ("ver %u... ", ver
);
515 ret
= kadm5_log_replay(server_context
, op
, ver
, len
, sp
);
517 krb5_warn (server_context
->context
, ret
, "kadm5_log_replay");
525 iprop_replay(struct replay_options
*opt
, int argc
, char **argv
)
527 kadm5_server_context
*server_context
;
530 server_context
= get_kadmin_context(opt
->config_file_string
,
534 free(server_context
->log_context
.log_file
);
535 server_context
->log_context
.log_file
= strdup(argv
[0]);
536 if (server_context
->log_context
.log_file
== NULL
)
537 krb5_err(context
, 1, errno
, "strdup");
540 ret
= server_context
->db
->hdb_open(context
,
542 O_RDWR
| O_CREAT
, 0600);
544 krb5_err (context
, 1, ret
, "db->open");
546 ret
= kadm5_log_init (server_context
);
548 krb5_err (context
, 1, ret
, "kadm5_log_init");
550 ret
= kadm5_log_foreach(server_context
,
551 kadm_forward
| kadm_confirmed
| kadm_unconfirmed
,
552 NULL
, apply_entry
, opt
);
554 krb5_warn(context
, ret
, "kadm5_log_foreach");
555 ret
= kadm5_log_end (server_context
);
557 krb5_warn(context
, ret
, "kadm5_log_end");
558 ret
= server_context
->db
->hdb_close (context
, server_context
->db
);
560 krb5_err (context
, 1, ret
, "db->close");
562 kadm5_destroy(server_context
);
566 static int help_flag
;
567 static int version_flag
;
569 static struct getargs args
[] = {
570 { "version", 0, arg_flag
, &version_flag
,
573 { "help", 'h', arg_flag
, &help_flag
,
578 static int num_args
= sizeof(args
) / sizeof(args
[0]);
581 help(void *opt
, int argc
, char **argv
)
584 sl_help(commands
, 1, argv
- 1 /* XXX */);
586 SL_cmd
*c
= sl_match (commands
, argv
[0], 0);
588 fprintf (stderr
, "No such command: %s. "
589 "Try \"help\" for a list of commands\n",
593 static char shelp
[] = "--help";
599 fprintf(stderr
, "\n");
601 if(c
->help
&& *c
->help
)
602 fprintf (stderr
, "%s\n", c
->help
);
603 if((++c
)->name
&& c
->func
== NULL
) {
605 fprintf (stderr
, "Synonyms:");
606 while (c
->name
&& c
->func
== NULL
) {
607 fprintf (stderr
, "%s%s", f
? ", " : " ", (c
++)->name
);
610 fprintf (stderr
, "\n");
620 arg_printusage(args
, num_args
, NULL
, "command");
625 main(int argc
, char **argv
)
630 setprogname(argv
[0]);
632 if(getarg(args
, num_args
, argc
, argv
, &optidx
))
645 ret
= krb5_init_context(&context
);
647 errx(1, "krb5_init_context failed with: %d\n", ret
);
649 ret
= sl_command(commands
, argc
, argv
);
651 warnx ("unrecognized command: %s", argv
[0]);