|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/* kadmin/dbutil/dump.c - Dump a KDC database */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright 1990,1991,2001,2006,2008,2009,2013 by the Massachusetts Institute
|
|
Packit |
fd8b60 |
* of Technology. All Rights Reserved.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Export of this software from the United States of America may
|
|
Packit |
fd8b60 |
* require a specific license from the United States Government.
|
|
Packit |
fd8b60 |
* It is the responsibility of any person or organization contemplating
|
|
Packit |
fd8b60 |
* export to obtain such a license before exporting.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
|
Packit |
fd8b60 |
* distribute this software and its documentation for any purpose and
|
|
Packit |
fd8b60 |
* without fee is hereby granted, provided that the above copyright
|
|
Packit |
fd8b60 |
* notice appear in all copies and that both that copyright notice and
|
|
Packit |
fd8b60 |
* this permission notice appear in supporting documentation, and that
|
|
Packit |
fd8b60 |
* the name of M.I.T. not be used in advertising or publicity pertaining
|
|
Packit |
fd8b60 |
* to distribution of the software without specific, written prior
|
|
Packit |
fd8b60 |
* permission. Furthermore if you modify this software you must label
|
|
Packit |
fd8b60 |
* your software as modified software and not distribute it in such a
|
|
Packit |
fd8b60 |
* fashion that it might be confused with the original M.I.T. software.
|
|
Packit |
fd8b60 |
* M.I.T. makes no representations about the suitability of
|
|
Packit |
fd8b60 |
* this software for any purpose. It is provided "as is" without express
|
|
Packit |
fd8b60 |
* or implied warranty.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
|
Packit |
fd8b60 |
* Use is subject to license terms.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include <k5-int.h>
|
|
Packit |
fd8b60 |
#include <kadm5/admin.h>
|
|
Packit |
fd8b60 |
#include <kadm5/server_internal.h>
|
|
Packit |
fd8b60 |
#include <kdb.h>
|
|
Packit |
fd8b60 |
#include <com_err.h>
|
|
Packit |
fd8b60 |
#include "kdb5_util.h"
|
|
Packit |
fd8b60 |
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
|
|
Packit |
fd8b60 |
#include <regex.h>
|
|
Packit |
fd8b60 |
#endif /* HAVE_REGEX_H */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Needed for master key conversion. */
|
|
Packit |
fd8b60 |
static krb5_boolean mkey_convert;
|
|
Packit |
fd8b60 |
krb5_keyblock new_master_keyblock;
|
|
Packit |
fd8b60 |
krb5_kvno new_mkvno;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define K5Q1(x) #x
|
|
Packit |
fd8b60 |
#define K5Q(x) K5Q1(x)
|
|
Packit |
fd8b60 |
#define K5CONST_WIDTH_SCANF_STR(x) "%" K5Q(x) "s"
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Use compile(3) if no regcomp present. */
|
|
Packit |
fd8b60 |
#if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H)
|
|
Packit |
fd8b60 |
#define INIT char *sp = instring;
|
|
Packit |
fd8b60 |
#define GETC() (*sp++)
|
|
Packit |
fd8b60 |
#define PEEKC() (*sp)
|
|
Packit |
fd8b60 |
#define UNGETC(c) (--sp)
|
|
Packit |
fd8b60 |
#define RETURN(c) return(c)
|
|
Packit |
fd8b60 |
#define ERROR(c)
|
|
Packit |
fd8b60 |
#define RE_BUF_SIZE 1024
|
|
Packit |
fd8b60 |
#include <regexp.h>
|
|
Packit |
fd8b60 |
#endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
typedef krb5_error_code (*dump_func)(krb5_context context,
|
|
Packit |
fd8b60 |
krb5_db_entry *entry, const char *name,
|
|
Packit |
fd8b60 |
FILE *fp, krb5_boolean verbose,
|
|
Packit |
fd8b60 |
krb5_boolean omit_nra);
|
|
Packit |
fd8b60 |
typedef int (*load_func)(krb5_context context, const char *dumpfile, FILE *fp,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
typedef struct _dump_version {
|
|
Packit |
fd8b60 |
char *name;
|
|
Packit |
fd8b60 |
char *header;
|
|
Packit |
fd8b60 |
int updateonly;
|
|
Packit |
fd8b60 |
int iprop;
|
|
Packit |
fd8b60 |
int ipropx;
|
|
Packit |
fd8b60 |
dump_func dump_princ;
|
|
Packit |
fd8b60 |
osa_adb_iter_policy_func dump_policy;
|
|
Packit |
fd8b60 |
load_func load_record;
|
|
Packit |
fd8b60 |
} dump_version;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
struct dump_args {
|
|
Packit |
fd8b60 |
FILE *ofile;
|
|
Packit |
fd8b60 |
krb5_context context;
|
|
Packit |
fd8b60 |
char **names;
|
|
Packit |
fd8b60 |
int nnames;
|
|
Packit |
fd8b60 |
krb5_boolean verbose;
|
|
Packit |
fd8b60 |
krb5_boolean omit_nra; /* omit non-replicated attributes */
|
|
Packit |
fd8b60 |
dump_version *dump;
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* External data */
|
|
Packit |
fd8b60 |
extern krb5_db_entry *master_entry;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Re-encrypt the key_data with the new master key...
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
master_key_convert(krb5_context context, krb5_db_entry *db_entry)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
krb5_keyblock v5plainkey, *key_ptr, *tmp_mkey;
|
|
Packit |
fd8b60 |
krb5_keysalt keysalt;
|
|
Packit |
fd8b60 |
krb5_key_data new_key_data, *key_data;
|
|
Packit |
fd8b60 |
krb5_boolean is_mkey;
|
|
Packit |
fd8b60 |
krb5_kvno kvno;
|
|
Packit |
fd8b60 |
int i, j;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (is_mkey) {
|
|
Packit |
fd8b60 |
return add_new_mkey(context, db_entry, &new_master_keyblock,
|
|
Packit |
fd8b60 |
new_mkvno);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; i < db_entry->n_key_data; i++) {
|
|
Packit |
fd8b60 |
key_data = &db_entry->key_data[i];
|
|
Packit |
fd8b60 |
retval = krb5_dbe_find_mkey(context, db_entry, &tmp_mkey);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
retval = krb5_dbe_decrypt_key_data(context, tmp_mkey, key_data,
|
|
Packit |
fd8b60 |
&v5plainkey, &keysalt);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
memset(&new_key_data, 0, sizeof(new_key_data));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
key_ptr = &v5plainkey;
|
|
Packit |
fd8b60 |
kvno = key_data->key_data_kvno;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = krb5_dbe_encrypt_key_data(context, &new_master_keyblock,
|
|
Packit |
fd8b60 |
key_ptr, &keysalt, kvno,
|
|
Packit |
fd8b60 |
&new_key_data);
|
|
Packit |
fd8b60 |
if (retval)
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
krb5_free_keyblock_contents(context, &v5plainkey);
|
|
Packit |
fd8b60 |
for (j = 0; j < key_data->key_data_ver; j++) {
|
|
Packit |
fd8b60 |
if (key_data->key_data_length[j])
|
|
Packit |
fd8b60 |
free(key_data->key_data_contents[j]);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
*key_data = new_key_data;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
assert(new_mkvno > 0);
|
|
Packit |
fd8b60 |
return krb5_dbe_update_mkvno(context, db_entry, new_mkvno);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Create temp file for new dump to be named ofile. */
|
|
Packit |
fd8b60 |
static FILE *
|
|
Packit |
fd8b60 |
create_ofile(char *ofile, char **tmpname)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int fd = -1;
|
|
Packit |
fd8b60 |
FILE *f;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*tmpname = NULL;
|
|
Packit |
fd8b60 |
if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0)
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fd = mkstemp(*tmpname);
|
|
Packit |
fd8b60 |
if (fd == -1)
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
f = fdopen(fd, "w+");
|
|
Packit |
fd8b60 |
if (f != NULL)
|
|
Packit |
fd8b60 |
return f;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
error:
|
|
Packit |
fd8b60 |
com_err(progname, errno, _("while allocating temporary filename dump"));
|
|
Packit |
fd8b60 |
if (fd >= 0)
|
|
Packit |
fd8b60 |
unlink(*tmpname);
|
|
Packit |
fd8b60 |
exit(1);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Rename new dump file into place. */
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
finish_ofile(char *ofile, char **tmpname)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (rename(*tmpname, ofile) == -1) {
|
|
Packit |
fd8b60 |
com_err(progname, errno, _("while renaming dump file into place"));
|
|
Packit |
fd8b60 |
exit(1);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
free(*tmpname);
|
|
Packit |
fd8b60 |
*tmpname = NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Create the .dump_ok file. */
|
|
Packit |
fd8b60 |
static krb5_boolean
|
|
Packit |
fd8b60 |
prep_ok_file(krb5_context context, char *file_name, int *fd_out)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
static char ok[] = ".dump_ok";
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
char *file_ok = NULL;
|
|
Packit |
fd8b60 |
int fd = -1;
|
|
Packit |
fd8b60 |
krb5_boolean success = FALSE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*fd_out = -1;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (asprintf(&file_ok, "%s%s", file_name, ok) < 0) {
|
|
Packit |
fd8b60 |
com_err(progname, ENOMEM, _("while allocating dump_ok filename"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
|
Packit |
fd8b60 |
if (fd == -1) {
|
|
Packit |
fd8b60 |
com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
retval = krb5_lock_file(context, fd, KRB5_LOCKMODE_EXCLUSIVE);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
com_err(progname, retval, _("while locking 'ok' file, '%s'"), file_ok);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*fd_out = fd;
|
|
Packit |
fd8b60 |
fd = -1;
|
|
Packit |
fd8b60 |
success = TRUE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free(file_ok);
|
|
Packit |
fd8b60 |
if (fd != -1)
|
|
Packit |
fd8b60 |
close(fd);
|
|
Packit |
fd8b60 |
if (!success)
|
|
Packit |
fd8b60 |
exit_status++;
|
|
Packit |
fd8b60 |
return success;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Update the "ok" file.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
update_ok_file(krb5_context context, int fd)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
write(fd, "", 1);
|
|
Packit |
fd8b60 |
krb5_lock_file(context, fd, KRB5_LOCKMODE_UNLOCK);
|
|
Packit |
fd8b60 |
close(fd);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Return true if a principal name matches a regular expression or string. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
name_matches(char *name, struct dump_args *args)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
#if HAVE_REGCOMP
|
|
Packit |
fd8b60 |
regex_t reg;
|
|
Packit |
fd8b60 |
regmatch_t rmatch;
|
|
Packit |
fd8b60 |
int st;
|
|
Packit |
fd8b60 |
char errmsg[BUFSIZ];
|
|
Packit |
fd8b60 |
#elif HAVE_REGEXP_H
|
|
Packit |
fd8b60 |
char regexp_buffer[RE_BUF_SIZE];
|
|
Packit |
fd8b60 |
#elif HAVE_RE_COMP
|
|
Packit |
fd8b60 |
extern char *re_comp();
|
|
Packit |
fd8b60 |
char *re_result;
|
|
Packit |
fd8b60 |
#endif /* HAVE_RE_COMP */
|
|
Packit |
fd8b60 |
int i, match;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Check each regular expression in args. */
|
|
Packit |
fd8b60 |
match = args->nnames ? 0 : 1;
|
|
Packit |
fd8b60 |
for (i = 0; i < args->nnames && !match; i++) {
|
|
Packit |
fd8b60 |
#if HAVE_REGCOMP
|
|
Packit |
fd8b60 |
/* Compile the regular expression. */
|
|
Packit |
fd8b60 |
st = regcomp(®, args->names[i], REG_EXTENDED);
|
|
Packit |
fd8b60 |
if (st) {
|
|
Packit |
fd8b60 |
regerror(st, ®, errmsg, sizeof(errmsg));
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: regular expression error: %s\n"), progname,
|
|
Packit |
fd8b60 |
errmsg);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
/* See if we have a match. */
|
|
Packit |
fd8b60 |
st = regexec(®, name, 1, &rmatch, 0);
|
|
Packit |
fd8b60 |
if (st == 0) {
|
|
Packit |
fd8b60 |
/* See if it matches the whole name. */
|
|
Packit |
fd8b60 |
if (rmatch.rm_so == 0 && (size_t)rmatch.rm_eo == strlen(name))
|
|
Packit |
fd8b60 |
match = 1;
|
|
Packit |
fd8b60 |
} else if (st != REG_NOMATCH) {
|
|
Packit |
fd8b60 |
regerror(st, ®, errmsg, sizeof(errmsg));
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: regular expression match error: %s\n"),
|
|
Packit |
fd8b60 |
progname, errmsg);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
regfree(®);
|
|
Packit |
fd8b60 |
#elif HAVE_REGEXP_H
|
|
Packit |
fd8b60 |
/* Compile the regular expression. */
|
|
Packit |
fd8b60 |
compile(args->names[i], regexp_buffer, ®exp_buffer[RE_BUF_SIZE],
|
|
Packit |
fd8b60 |
'\0');
|
|
Packit |
fd8b60 |
if (step(name, regexp_buffer)) {
|
|
Packit |
fd8b60 |
if (loc1 == name && loc2 == &name[strlen(name)])
|
|
Packit |
fd8b60 |
match = 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#elif HAVE_RE_COMP
|
|
Packit |
fd8b60 |
/* Compile the regular expression. */
|
|
Packit |
fd8b60 |
re_result = re_comp(args->names[i]);
|
|
Packit |
fd8b60 |
if (re_result) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: regular expression error: %s\n"), progname,
|
|
Packit |
fd8b60 |
re_result);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (re_exec(name))
|
|
Packit |
fd8b60 |
match = 1;
|
|
Packit |
fd8b60 |
#else /* HAVE_RE_COMP */
|
|
Packit |
fd8b60 |
/* If no regular expression support, then just compare the strings. */
|
|
Packit |
fd8b60 |
if (!strcmp(args->names[i], name))
|
|
Packit |
fd8b60 |
match = 1;
|
|
Packit |
fd8b60 |
#endif /* HAVE_REGCOMP */
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return match;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Output "-1" if len is 0; otherwise output len bytes of data in hex. */
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
dump_octets_or_minus1(FILE *fp, unsigned char *data, size_t len)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (len > 0) {
|
|
Packit |
fd8b60 |
for (; len > 0; len--)
|
|
Packit |
fd8b60 |
fprintf(fp, "%02x", *data++);
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
fprintf(fp, "-1");
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Dump TL data; common to principals and policies.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* If filter_kadm then the KRB5_TL_KADM_DATA (where a principal's policy
|
|
Packit |
fd8b60 |
* name is stored) is filtered out. This is for dump formats that don't
|
|
Packit |
fd8b60 |
* support policies.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
dump_tl_data(FILE *ofile, krb5_tl_data *tlp, krb5_boolean filter_kadm)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
for (; tlp != NULL; tlp = tlp->tl_data_next) {
|
|
Packit |
fd8b60 |
if (tlp->tl_data_type == KRB5_TL_KADM_DATA && filter_kadm)
|
|
Packit |
fd8b60 |
continue;
|
|
Packit |
fd8b60 |
fprintf(ofile, "\t%d\t%d\t", (int)tlp->tl_data_type,
|
|
Packit |
fd8b60 |
(int)tlp->tl_data_length);
|
|
Packit |
fd8b60 |
dump_octets_or_minus1(ofile, tlp->tl_data_contents,
|
|
Packit |
fd8b60 |
tlp->tl_data_length);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Dump a principal entry in krb5 beta 7 format. Omit kadmin tl-data if kadm
|
|
Packit |
fd8b60 |
* is false. */
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
k5beta7_common(krb5_context context, krb5_db_entry *entry,
|
|
Packit |
fd8b60 |
const char *name, FILE *fp, krb5_boolean verbose,
|
|
Packit |
fd8b60 |
krb5_boolean omit_nra, krb5_boolean kadm)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_tl_data *tlp;
|
|
Packit |
fd8b60 |
krb5_key_data *kdata;
|
|
Packit |
fd8b60 |
int counter, skip, i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* The dump format is as follows:
|
|
Packit |
fd8b60 |
* len strlen(name) n_tl_data n_key_data e_length
|
|
Packit |
fd8b60 |
* name
|
|
Packit |
fd8b60 |
* attributes max_life max_renewable_life expiration
|
|
Packit |
fd8b60 |
* pw_expiration last_success last_failed fail_auth_count
|
|
Packit |
fd8b60 |
* n_tl_data*[type length <contents>]
|
|
Packit |
fd8b60 |
* n_key_data*[ver kvno ver*(type length <contents>)]
|
|
Packit |
fd8b60 |
* <e_data>
|
|
Packit |
fd8b60 |
* Fields which are not encapsulated by angle-brackets are to appear
|
|
Packit |
fd8b60 |
* verbatim. A bracketed field's absence is indicated by a -1 in its
|
|
Packit |
fd8b60 |
* place.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Make sure that the tagged list is reasonably correct. */
|
|
Packit |
fd8b60 |
counter = skip = 0;
|
|
Packit |
fd8b60 |
for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) {
|
|
Packit |
fd8b60 |
/* Don't dump tl data types we know aren't understood by earlier
|
|
Packit |
fd8b60 |
* versions. */
|
|
Packit |
fd8b60 |
if (tlp->tl_data_type == KRB5_TL_KADM_DATA && !kadm)
|
|
Packit |
fd8b60 |
skip++;
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
counter++;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (counter + skip != entry->n_tl_data) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: tagged data list inconsistency for %s "
|
|
Packit |
fd8b60 |
"(counted %d, stored %d)\n"), progname, name,
|
|
Packit |
fd8b60 |
counter + skip, (int)entry->n_tl_data);
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Write out header. */
|
|
Packit |
fd8b60 |
fprintf(fp, "princ\t%d\t%lu\t%d\t%d\t%d\t%s\t", (int)entry->len,
|
|
Packit |
fd8b60 |
(unsigned long)strlen(name), counter, (int)entry->n_key_data,
|
|
Packit |
fd8b60 |
(int)entry->e_length, name);
|
|
Packit |
fd8b60 |
fprintf(fp, "%d\t%d\t%d\t%u\t%u\t%u\t%u\t%d", entry->attributes,
|
|
Packit |
fd8b60 |
entry->max_life, entry->max_renewable_life,
|
|
Packit |
fd8b60 |
(unsigned int)entry->expiration,
|
|
Packit |
fd8b60 |
(unsigned int)entry->pw_expiration,
|
|
Packit |
fd8b60 |
(unsigned int)(omit_nra ? 0 : entry->last_success),
|
|
Packit |
fd8b60 |
(unsigned int)(omit_nra ? 0 : entry->last_failed),
|
|
Packit |
fd8b60 |
omit_nra ? 0 : entry->fail_auth_count);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Write out tagged data. */
|
|
Packit |
fd8b60 |
dump_tl_data(fp, entry->tl_data, !kadm);
|
|
Packit |
fd8b60 |
fprintf(fp, "\t");
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Write out key data. */
|
|
Packit |
fd8b60 |
for (counter = 0; counter < entry->n_key_data; counter++) {
|
|
Packit |
fd8b60 |
kdata = &entry->key_data[counter];
|
|
Packit |
fd8b60 |
fprintf(fp, "%d\t%d\t", (int)kdata->key_data_ver,
|
|
Packit |
fd8b60 |
(int)kdata->key_data_kvno);
|
|
Packit |
fd8b60 |
for (i = 0; i < kdata->key_data_ver; i++) {
|
|
Packit |
fd8b60 |
fprintf(fp, "%d\t%d\t", kdata->key_data_type[i],
|
|
Packit |
fd8b60 |
kdata->key_data_length[i]);
|
|
Packit |
fd8b60 |
dump_octets_or_minus1(fp, kdata->key_data_contents[i],
|
|
Packit |
fd8b60 |
kdata->key_data_length[i]);
|
|
Packit |
fd8b60 |
fprintf(fp, "\t");
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Write out extra data. */
|
|
Packit |
fd8b60 |
dump_octets_or_minus1(fp, entry->e_data, entry->e_length);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Write trailer. */
|
|
Packit |
fd8b60 |
fprintf(fp, ";\n");
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (verbose)
|
|
Packit |
fd8b60 |
fprintf(stderr, "%s\n", name);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Output a dump record in krb5b7 format. */
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
dump_k5beta7_princ(krb5_context context, krb5_db_entry *entry,
|
|
Packit |
fd8b60 |
const char *name, FILE *fp, krb5_boolean verbose,
|
|
Packit |
fd8b60 |
krb5_boolean omit_nra)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return k5beta7_common(context, entry, name, fp, verbose, omit_nra, FALSE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
dump_k5beta7_princ_withpolicy(krb5_context context, krb5_db_entry *entry,
|
|
Packit |
fd8b60 |
const char *name, FILE *fp, krb5_boolean verbose,
|
|
Packit |
fd8b60 |
krb5_boolean omit_nra)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return k5beta7_common(context, entry, name, fp, verbose, omit_nra, TRUE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
dump_k5beta7_policy(void *data, osa_policy_ent_t entry)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
struct dump_args *arg = data;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", entry->name,
|
|
Packit |
fd8b60 |
entry->pw_min_life, entry->pw_max_life, entry->pw_min_length,
|
|
Packit |
fd8b60 |
entry->pw_min_classes, entry->pw_history_num, 0);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
dump_r1_8_policy(void *data, osa_policy_ent_t entry)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
struct dump_args *arg = data;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
|
|
Packit |
fd8b60 |
entry->name, entry->pw_min_life, entry->pw_max_life,
|
|
Packit |
fd8b60 |
entry->pw_min_length, entry->pw_min_classes, entry->pw_history_num,
|
|
Packit |
fd8b60 |
0, entry->pw_max_fail, entry->pw_failcnt_interval,
|
|
Packit |
fd8b60 |
entry->pw_lockout_duration);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
dump_r1_11_policy(void *data, osa_policy_ent_t entry)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
struct dump_args *arg = data;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t"
|
|
Packit |
fd8b60 |
"%d\t%d\t%d\t%s\t%d", entry->name, entry->pw_min_life,
|
|
Packit |
fd8b60 |
entry->pw_max_life, entry->pw_min_length, entry->pw_min_classes,
|
|
Packit |
fd8b60 |
entry->pw_history_num, 0, entry->pw_max_fail,
|
|
Packit |
fd8b60 |
entry->pw_failcnt_interval, entry->pw_lockout_duration,
|
|
Packit |
fd8b60 |
entry->attributes, entry->max_life, entry->max_renewable_life,
|
|
Packit |
fd8b60 |
entry->allowed_keysalts ? entry->allowed_keysalts : "-",
|
|
Packit |
fd8b60 |
entry->n_tl_data);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
dump_tl_data(arg->ofile, entry->tl_data, FALSE);
|
|
Packit |
fd8b60 |
fprintf(arg->ofile, "\n");
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
dump_iterator(void *ptr, krb5_db_entry *entry)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
struct dump_args *args = ptr;
|
|
Packit |
fd8b60 |
char *name;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_unparse_name(args->context, entry->princ, &name);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while unparsing principal name"));
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Re-encode the keys in the new master key, if necessary. */
|
|
Packit |
fd8b60 |
if (mkey_convert) {
|
|
Packit |
fd8b60 |
ret = master_key_convert(args->context, entry);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while converting %s to new master key"),
|
|
Packit |
fd8b60 |
name);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Don't dump this entry if we have match strings and it doesn't match. */
|
|
Packit |
fd8b60 |
if (args->nnames > 0 && !name_matches(name, args))
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = args->dump->dump_princ(args->context, entry, name, args->ofile,
|
|
Packit |
fd8b60 |
args->verbose, args->omit_nra);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free(name);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
load_err(const char *fname, int lineno, const char *msg)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s(%d): %s\n"), fname, lineno, msg);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read a string of bytes. Increment *lp for each newline. Return 0 on
|
|
Packit |
fd8b60 |
* success, 1 on failure. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
read_string(FILE *f, char *buf, int len, int *lp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int c, i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; i < len; i++) {
|
|
Packit |
fd8b60 |
c = fgetc(f);
|
|
Packit |
fd8b60 |
if (c < 0)
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
if (c == '\n')
|
|
Packit |
fd8b60 |
(*lp)++;
|
|
Packit |
fd8b60 |
buf[i] = c;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
buf[len] = '\0';
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read a string of two-character representations of bytes. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
read_octet_string(FILE *f, unsigned char *buf, int len)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int c, i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; i < len; i++) {
|
|
Packit |
fd8b60 |
if (fscanf(f, "%02x", &c) != 1)
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
buf[i] = c;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read the end of a dumpfile record. */
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
read_record_end(FILE *f, const char *fn, int lineno)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int ch;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((ch = fgetc(f)) != ';' || (ch = fgetc(f)) != '\n') {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s(%d): ignoring trash at end of line: "), fn,
|
|
Packit |
fd8b60 |
lineno);
|
|
Packit |
fd8b60 |
while (ch != '\n') {
|
|
Packit |
fd8b60 |
putc(ch, stderr);
|
|
Packit |
fd8b60 |
ch = fgetc(f);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
putc(ch, stderr);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate and form a TL data list of a desired size. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
alloc_tl_data(krb5_int16 n_tl_data, krb5_tl_data **tldp)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_tl_data **tlp = tldp;
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 0; i < n_tl_data; i++) {
|
|
Packit |
fd8b60 |
*tlp = calloc(1, sizeof(krb5_tl_data));
|
|
Packit |
fd8b60 |
if (*tlp == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM; /* caller cleans up */
|
|
Packit |
fd8b60 |
tlp = &((*tlp)->tl_data_next);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* If len is zero, read the string "-1" from fp. Otherwise allocate space and
|
|
Packit |
fd8b60 |
* read len octets. Return 0 on success, 1 on failure. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
read_octets_or_minus1(FILE *fp, size_t len, unsigned char **out)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int ival;
|
|
Packit |
fd8b60 |
unsigned char *buf;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*out = NULL;
|
|
Packit |
fd8b60 |
if (len == 0)
|
|
Packit |
fd8b60 |
return fscanf(fp, "%d", &ival) != 1 || ival != -1;
|
|
Packit |
fd8b60 |
buf = malloc(len);
|
|
Packit |
fd8b60 |
if (buf == NULL)
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
if (read_octet_string(fp, buf, len)) {
|
|
Packit |
fd8b60 |
free(buf);
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
*out = buf;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read TL data for a principal or policy. Print an error and return -1 on
|
|
Packit |
fd8b60 |
* failure. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_tl_data(const char *fname, FILE *filep, int lineno,
|
|
Packit |
fd8b60 |
krb5_tl_data *tl_data)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_tl_data *tl;
|
|
Packit |
fd8b60 |
int nread, i1;
|
|
Packit |
fd8b60 |
unsigned int u1;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (tl = tl_data; tl; tl = tl->tl_data_next) {
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%d\t%u\t", &i1, &u1;;
|
|
Packit |
fd8b60 |
if (nread != 2) {
|
|
Packit |
fd8b60 |
load_err(fname, lineno,
|
|
Packit |
fd8b60 |
_("cannot read tagged data type and length"));
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (i1 < INT16_MIN || i1 > INT16_MAX || u1 > UINT16_MAX) {
|
|
Packit |
fd8b60 |
load_err(fname, lineno, _("data type or length overflowed"));
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
tl->tl_data_type = i1;
|
|
Packit |
fd8b60 |
tl->tl_data_length = u1;
|
|
Packit |
fd8b60 |
if (read_octets_or_minus1(filep, tl->tl_data_length,
|
|
Packit |
fd8b60 |
&tl->tl_data_contents)) {
|
|
Packit |
fd8b60 |
load_err(fname, lineno, _("cannot read tagged data contents"));
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read a beta 7 entry and add it to the database. Return -1 for end of file,
|
|
Packit |
fd8b60 |
* 0 for success and 1 for failure. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int retval, nread, i, j;
|
|
Packit |
fd8b60 |
krb5_db_entry *dbentry;
|
|
Packit |
fd8b60 |
int t1, t2, t3, t4;
|
|
Packit |
fd8b60 |
unsigned int u1, u2, u3, u4, u5;
|
|
Packit |
fd8b60 |
char *name = NULL;
|
|
Packit |
fd8b60 |
krb5_key_data *kp = NULL, *kd;
|
|
Packit |
fd8b60 |
krb5_tl_data *tl;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
dbentry = calloc(1, sizeof(*dbentry));
|
|
Packit |
fd8b60 |
if (dbentry == NULL)
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
(*linenop)++;
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%u\t%u\t%u\t%u\t%u\t", &u1, &u2, &u3, &u4, &u5;;
|
|
Packit |
fd8b60 |
if (nread == EOF) {
|
|
Packit |
fd8b60 |
retval = -1;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (nread != 5) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("cannot match size tokens"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get memory for flattened principal name */
|
|
Packit |
fd8b60 |
name = malloc(u2 + 1);
|
|
Packit |
fd8b60 |
if (name == NULL)
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get memory for and form tagged data linked list */
|
|
Packit |
fd8b60 |
if (u3 > UINT16_MAX) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("cannot allocate tl_data (too large)"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (alloc_tl_data(u3, &dbentry->tl_data))
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
dbentry->n_tl_data = u3;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get memory for key list */
|
|
Packit |
fd8b60 |
if (u4 && (kp = calloc(u4, sizeof(krb5_key_data))) == NULL)
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
dbentry->len = u1;
|
|
Packit |
fd8b60 |
dbentry->n_key_data = u4;
|
|
Packit |
fd8b60 |
dbentry->e_length = u5;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (kp != NULL) {
|
|
Packit |
fd8b60 |
dbentry->key_data = kp;
|
|
Packit |
fd8b60 |
kp = NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read in and parse the principal name */
|
|
Packit |
fd8b60 |
if (read_string(filep, name, u2, linenop)) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("cannot read name string"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
ret = krb5_parse_name(context, name, &dbentry->princ);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while parsing name %s"), name);
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get the fixed principal attributes */
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%d\t%d\t%d\t%u\t%u\t%d\t%d\t%d\t",
|
|
Packit |
fd8b60 |
&t1, &t2, &t3, &u1, &u2, &u3, &u4, &u5;;
|
|
Packit |
fd8b60 |
if (nread != 8) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("cannot read principal attributes"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
dbentry->attributes = t1;
|
|
Packit |
fd8b60 |
dbentry->max_life = t2;
|
|
Packit |
fd8b60 |
dbentry->max_renewable_life = t3;
|
|
Packit |
fd8b60 |
dbentry->expiration = u1;
|
|
Packit |
fd8b60 |
dbentry->pw_expiration = u2;
|
|
Packit |
fd8b60 |
dbentry->last_success = u3;
|
|
Packit |
fd8b60 |
dbentry->last_failed = u4;
|
|
Packit |
fd8b60 |
dbentry->fail_auth_count = u5;
|
|
Packit |
fd8b60 |
dbentry->mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
|
|
Packit |
fd8b60 |
KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
|
|
Packit |
fd8b60 |
KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS |
|
|
Packit |
fd8b60 |
KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read tagged data. */
|
|
Packit |
fd8b60 |
if (dbentry->n_tl_data) {
|
|
Packit |
fd8b60 |
if (process_tl_data(fname, filep, *linenop, dbentry->tl_data))
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
for (tl = dbentry->tl_data; tl; tl = tl->tl_data_next) {
|
|
Packit |
fd8b60 |
/* test to set mask fields */
|
|
Packit |
fd8b60 |
if (tl->tl_data_type == KRB5_TL_KADM_DATA) {
|
|
Packit |
fd8b60 |
XDR xdrs;
|
|
Packit |
fd8b60 |
osa_princ_ent_rec osa_princ_ent;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Assuming aux_attributes will always be
|
|
Packit |
fd8b60 |
* there
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
dbentry->mask |= KADM5_AUX_ATTRIBUTES;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* test for an actual policy reference */
|
|
Packit |
fd8b60 |
memset(&osa_princ_ent, 0, sizeof(osa_princ_ent));
|
|
Packit |
fd8b60 |
xdrmem_create(&xdrs, (char *)tl->tl_data_contents,
|
|
Packit |
fd8b60 |
tl->tl_data_length, XDR_DECODE);
|
|
Packit |
fd8b60 |
if (xdr_osa_princ_ent_rec(&xdrs, &osa_princ_ent)) {
|
|
Packit |
fd8b60 |
if ((osa_princ_ent.aux_attributes & KADM5_POLICY) &&
|
|
Packit |
fd8b60 |
osa_princ_ent.policy != NULL)
|
|
Packit |
fd8b60 |
dbentry->mask |= KADM5_POLICY;
|
|
Packit |
fd8b60 |
kdb_free_entry(NULL, NULL, &osa_princ_ent);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
xdr_destroy(&xdrs);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
dbentry->mask |= KADM5_TL_DATA;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get the key data. */
|
|
Packit |
fd8b60 |
for (i = 0; i < dbentry->n_key_data; i++) {
|
|
Packit |
fd8b60 |
kd = &dbentry->key_data[i];
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%d\t%d\t", &t1, &t2;;
|
|
Packit |
fd8b60 |
if (nread != 2) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("cannot read key size and version"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (t1 > KRB5_KDB_V1_KEY_DATA_ARRAY) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("unsupported key_data_ver version"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
kd->key_data_ver = t1;
|
|
Packit |
fd8b60 |
kd->key_data_kvno = t2;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (j = 0; j < t1; j++) {
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%d\t%d\t", &t3, &t4;;
|
|
Packit |
fd8b60 |
if (nread != 2 || t4 < 0) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop,
|
|
Packit |
fd8b60 |
_("cannot read key type and length"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
kd->key_data_type[j] = t3;
|
|
Packit |
fd8b60 |
kd->key_data_length[j] = t4;
|
|
Packit |
fd8b60 |
if (read_octets_or_minus1(filep, t4, &kd->key_data_contents[j])) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("cannot read key data"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (dbentry->n_key_data)
|
|
Packit |
fd8b60 |
dbentry->mask |= KADM5_KEY_DATA;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get the extra data */
|
|
Packit |
fd8b60 |
if (read_octets_or_minus1(filep, dbentry->e_length, &dbentry->e_data)) {
|
|
Packit |
fd8b60 |
load_err(fname, *linenop, _("cannot read extra data"));
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Finally, find the end of the record. */
|
|
Packit |
fd8b60 |
read_record_end(filep, fname, *linenop);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_db_put_principal(context, dbentry);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while storing %s"), name);
|
|
Packit |
fd8b60 |
goto fail;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (verbose)
|
|
Packit |
fd8b60 |
fprintf(stderr, "%s\n", name);
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free(kp);
|
|
Packit |
fd8b60 |
free(name);
|
|
Packit |
fd8b60 |
krb5_db_free_principal(context, dbentry);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fail:
|
|
Packit |
fd8b60 |
retval = 1;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_k5beta7_policy(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
osa_policy_ent_rec rec;
|
|
Packit |
fd8b60 |
char namebuf[1024];
|
|
Packit |
fd8b60 |
unsigned int refcnt;
|
|
Packit |
fd8b60 |
int nread, ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
memset(&rec, 0, sizeof(rec));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
(*linenop)++;
|
|
Packit |
fd8b60 |
rec.name = namebuf;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u", rec.name,
|
|
Packit |
fd8b60 |
&rec.pw_min_life, &rec.pw_max_life, &rec.pw_min_length,
|
|
Packit |
fd8b60 |
&rec.pw_min_classes, &rec.pw_history_num, &refcnt);
|
|
Packit |
fd8b60 |
if (nread == EOF)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
if (nread != 7) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_db_create_policy(context, &rec);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
ret = krb5_db_put_policy(context, &rec);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while creating policy"));
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (verbose)
|
|
Packit |
fd8b60 |
fprintf(stderr, _("created policy %s\n"), rec.name);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_r1_8_policy(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
osa_policy_ent_rec rec;
|
|
Packit |
fd8b60 |
char namebuf[1024];
|
|
Packit |
fd8b60 |
unsigned int refcnt;
|
|
Packit |
fd8b60 |
int nread, ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
memset(&rec, 0, sizeof(rec));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
(*linenop)++;
|
|
Packit |
fd8b60 |
rec.name = namebuf;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
|
|
Packit |
fd8b60 |
rec.name, &rec.pw_min_life, &rec.pw_max_life,
|
|
Packit |
fd8b60 |
&rec.pw_min_length, &rec.pw_min_classes,
|
|
Packit |
fd8b60 |
&rec.pw_history_num, &refcnt, &rec.pw_max_fail,
|
|
Packit |
fd8b60 |
&rec.pw_failcnt_interval, &rec.pw_lockout_duration);
|
|
Packit |
fd8b60 |
if (nread == EOF)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
if (nread != 10) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_db_create_policy(context, &rec);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
ret = krb5_db_put_policy(context, &rec);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while creating policy"));
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (verbose)
|
|
Packit |
fd8b60 |
fprintf(stderr, "created policy %s\n", rec.name);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_r1_11_policy(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
osa_policy_ent_rec rec;
|
|
Packit |
fd8b60 |
krb5_tl_data *tl, *tl_next;
|
|
Packit |
fd8b60 |
char namebuf[1024];
|
|
Packit |
fd8b60 |
char keysaltbuf[KRB5_KDB_MAX_ALLOWED_KS_LEN + 1];
|
|
Packit |
fd8b60 |
unsigned int refcnt;
|
|
Packit |
fd8b60 |
int nread, c, ret = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
memset(&rec, 0, sizeof(rec));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
(*linenop)++;
|
|
Packit |
fd8b60 |
rec.name = namebuf;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Due to a historical error, iprop dumps use the same version before and
|
|
Packit |
fd8b60 |
* after the 1.11 policy extensions. So we need to accept both 1.8-format
|
|
Packit |
fd8b60 |
* and 1.11-format policy entries. Begin by reading the 1.8 fields.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
|
|
Packit |
fd8b60 |
rec.name, &rec.pw_min_life, &rec.pw_max_life,
|
|
Packit |
fd8b60 |
&rec.pw_min_length, &rec.pw_min_classes,
|
|
Packit |
fd8b60 |
&rec.pw_history_num, &refcnt, &rec.pw_max_fail,
|
|
Packit |
fd8b60 |
&rec.pw_failcnt_interval, &rec.pw_lockout_duration);
|
|
Packit |
fd8b60 |
if (nread == EOF)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
if (nread != 10) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* The next character should be a newline (1.8) or a tab (1.11). */
|
|
Packit |
fd8b60 |
c = getc(filep);
|
|
Packit |
fd8b60 |
if (c == EOF)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
if (c != '\n') {
|
|
Packit |
fd8b60 |
/* Read the additional 1.11-format fields. */
|
|
Packit |
fd8b60 |
rec.allowed_keysalts = keysaltbuf;
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%u\t%u\t%u\t"
|
|
Packit |
fd8b60 |
K5CONST_WIDTH_SCANF_STR(KRB5_KDB_MAX_ALLOWED_KS_LEN)
|
|
Packit |
fd8b60 |
"\t%hd", &rec.attributes, &rec.max_life,
|
|
Packit |
fd8b60 |
&rec.max_renewable_life, rec.allowed_keysalts,
|
|
Packit |
fd8b60 |
&rec.n_tl_data);
|
|
Packit |
fd8b60 |
if (nread == EOF)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
if (nread != 5) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (rec.allowed_keysalts && !strcmp(rec.allowed_keysalts, "-"))
|
|
Packit |
fd8b60 |
rec.allowed_keysalts = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get TL data */
|
|
Packit |
fd8b60 |
ret = alloc_tl_data(rec.n_tl_data, &rec.tl_data);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = process_tl_data(fname, filep, *linenop, rec.tl_data);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_db_create_policy(context, &rec);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
ret = krb5_db_put_policy(context, &rec);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while creating policy"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (verbose)
|
|
Packit |
fd8b60 |
fprintf(stderr, "created policy %s\n", rec.name);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
for (tl = rec.tl_data; tl; tl = tl_next) {
|
|
Packit |
fd8b60 |
tl_next = tl->tl_data_next;
|
|
Packit |
fd8b60 |
free(tl->tl_data_contents);
|
|
Packit |
fd8b60 |
free(tl);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return ret ? 1 : 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read a record which is tagged with "princ" or "policy", calling princfn
|
|
Packit |
fd8b60 |
* or policyfn as appropriate. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_tagged(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop, load_func princfn,
|
|
Packit |
fd8b60 |
load_func policyfn)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int nread;
|
|
Packit |
fd8b60 |
char rectype[100];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
nread = fscanf(filep, "%99s\t", rectype);
|
|
Packit |
fd8b60 |
if (nread == EOF)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
if (nread != 1)
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
if (strcmp(rectype, "princ") == 0)
|
|
Packit |
fd8b60 |
return (*princfn)(context, fname, filep, verbose, linenop);
|
|
Packit |
fd8b60 |
if (strcmp(rectype, "policy") == 0)
|
|
Packit |
fd8b60 |
return (*policyfn)(context, fname, filep, verbose, linenop);
|
|
Packit |
fd8b60 |
if (strcmp(rectype, "End") == 0) /* Only expected for OV format */
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fprintf(stderr, _("unknown record type \"%s\"\n"), rectype);
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_k5beta7_record(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return process_tagged(context, fname, filep, verbose, linenop,
|
|
Packit |
fd8b60 |
process_k5beta7_princ, process_k5beta7_policy);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_r1_8_record(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return process_tagged(context, fname, filep, verbose, linenop,
|
|
Packit |
fd8b60 |
process_k5beta7_princ, process_r1_8_policy);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
process_r1_11_record(krb5_context context, const char *fname, FILE *filep,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, int *linenop)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return process_tagged(context, fname, filep, verbose, linenop,
|
|
Packit |
fd8b60 |
process_k5beta7_princ, process_r1_11_policy);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
dump_version beta7_version = {
|
|
Packit |
fd8b60 |
"Kerberos version 5",
|
|
Packit |
fd8b60 |
"kdb5_util load_dump version 4\n",
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
dump_k5beta7_princ,
|
|
Packit |
fd8b60 |
dump_k5beta7_policy,
|
|
Packit |
fd8b60 |
process_k5beta7_record,
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
dump_version r1_3_version = {
|
|
Packit |
fd8b60 |
"Kerberos version 5 release 1.3",
|
|
Packit |
fd8b60 |
"kdb5_util load_dump version 5\n",
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
dump_k5beta7_princ_withpolicy,
|
|
Packit |
fd8b60 |
dump_k5beta7_policy,
|
|
Packit |
fd8b60 |
process_k5beta7_record,
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
dump_version r1_8_version = {
|
|
Packit |
fd8b60 |
"Kerberos version 5 release 1.8",
|
|
Packit |
fd8b60 |
"kdb5_util load_dump version 6\n",
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
dump_k5beta7_princ_withpolicy,
|
|
Packit |
fd8b60 |
dump_r1_8_policy,
|
|
Packit |
fd8b60 |
process_r1_8_record,
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
dump_version r1_11_version = {
|
|
Packit |
fd8b60 |
"Kerberos version 5 release 1.11",
|
|
Packit |
fd8b60 |
"kdb5_util load_dump version 7\n",
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
dump_k5beta7_princ_withpolicy,
|
|
Packit |
fd8b60 |
dump_r1_11_policy,
|
|
Packit |
fd8b60 |
process_r1_11_record,
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
dump_version iprop_version = {
|
|
Packit |
fd8b60 |
"Kerberos iprop version",
|
|
Packit |
fd8b60 |
"iprop",
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
1,
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
dump_k5beta7_princ_withpolicy,
|
|
Packit |
fd8b60 |
dump_k5beta7_policy,
|
|
Packit |
fd8b60 |
process_k5beta7_record,
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
dump_version ipropx_1_version = {
|
|
Packit |
fd8b60 |
"Kerberos iprop extensible version",
|
|
Packit |
fd8b60 |
"ipropx",
|
|
Packit |
fd8b60 |
0,
|
|
Packit |
fd8b60 |
1,
|
|
Packit |
fd8b60 |
1,
|
|
Packit |
fd8b60 |
dump_k5beta7_princ_withpolicy,
|
|
Packit |
fd8b60 |
dump_r1_11_policy,
|
|
Packit |
fd8b60 |
process_r1_11_record,
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Read the dump header. Return 1 on success, 0 if the file is not a
|
|
Packit |
fd8b60 |
* recognized iprop dump format. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
parse_iprop_header(char *buf, dump_version **dv, kdb_last_t *last)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char head[128];
|
|
Packit |
fd8b60 |
int nread;
|
|
Packit |
fd8b60 |
uint32_t u[4];
|
|
Packit |
fd8b60 |
uint32_t *up = &u[0];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
nread = sscanf(buf, "%127s %u %u %u %u", head, &u[0], &u[1], &u[2], &u[3]);
|
|
Packit |
fd8b60 |
if (nread < 1)
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (!strcmp(head, ipropx_1_version.header)) {
|
|
Packit |
fd8b60 |
if (nread != 5)
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
if (u[0] == IPROPX_VERSION_0) {
|
|
Packit |
fd8b60 |
*dv = &iprop_version;
|
|
Packit |
fd8b60 |
} else if (u[0] == IPROPX_VERSION_1) {
|
|
Packit |
fd8b60 |
*dv = &ipropx_1_version;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: Unknown iprop dump version %d\n"), progname,
|
|
Packit |
fd8b60 |
u[0]);
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
up = &u[1];
|
|
Packit |
fd8b60 |
} else if (!strcmp(head, iprop_version.header)) {
|
|
Packit |
fd8b60 |
if (nread != 4)
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
*dv = &iprop_version;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
fprintf(stderr, "Invalid iprop header\n");
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
last->last_sno = *up++;
|
|
Packit |
fd8b60 |
last->last_time.seconds = *up++;
|
|
Packit |
fd8b60 |
last->last_time.useconds = *up++;
|
|
Packit |
fd8b60 |
return 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Return true if the serial number and timestamp in an existing dump file is
|
|
Packit |
fd8b60 |
* in the ulog. */
|
|
Packit |
fd8b60 |
static krb5_boolean
|
|
Packit |
fd8b60 |
current_dump_sno_in_ulog(krb5_context context, const char *ifile)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
update_status_t status;
|
|
Packit |
fd8b60 |
dump_version *junk;
|
|
Packit |
fd8b60 |
kdb_last_t last;
|
|
Packit |
fd8b60 |
char buf[BUFSIZ], *r;
|
|
Packit |
fd8b60 |
FILE *f;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
f = fopen(ifile, "r");
|
|
Packit |
fd8b60 |
if (f == NULL)
|
|
Packit |
fd8b60 |
return 0; /* aliasing other errors to ENOENT here is OK */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
r = fgets(buf, sizeof(buf), f);
|
|
Packit |
fd8b60 |
fclose(f);
|
|
Packit |
fd8b60 |
if (r == NULL)
|
|
Packit |
fd8b60 |
return errno ? -1 : 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (!parse_iprop_header(buf, &junk, &last))
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
status = ulog_get_sno_status(context, &last);
|
|
Packit |
fd8b60 |
return status == UPDATE_OK || status == UPDATE_NIL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* usage is:
|
|
Packit |
fd8b60 |
* dump_db [-b7] [-r13] [-r18] [-verbose] [-mkey_convert]
|
|
Packit |
fd8b60 |
* [-new_mkey_file mkey_file] [-rev] [-recurse]
|
|
Packit |
fd8b60 |
* [filename [principals...]]
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
void
|
|
Packit |
fd8b60 |
dump_db(int argc, char **argv)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
FILE *f;
|
|
Packit |
fd8b60 |
struct dump_args args;
|
|
Packit |
fd8b60 |
char *ofile = NULL, *tmpofile = NULL, *new_mkey_file = NULL;
|
|
Packit |
fd8b60 |
krb5_error_code ret, retval;
|
|
Packit |
fd8b60 |
dump_version *dump;
|
|
Packit |
fd8b60 |
int aindex, ok_fd = -1;
|
|
Packit |
fd8b60 |
bool_t dump_sno = FALSE;
|
|
Packit |
fd8b60 |
kdb_log_context *log_ctx;
|
|
Packit |
fd8b60 |
unsigned int ipropx_version = IPROPX_VERSION_0;
|
|
Packit |
fd8b60 |
krb5_kvno kt_kvno;
|
|
Packit |
fd8b60 |
krb5_boolean conditional = FALSE;
|
|
Packit |
fd8b60 |
kdb_last_t last;
|
|
Packit |
fd8b60 |
krb5_flags iterflags = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Parse the arguments. */
|
|
Packit |
fd8b60 |
dump = &r1_11_version;
|
|
Packit |
fd8b60 |
args.verbose = FALSE;
|
|
Packit |
fd8b60 |
args.omit_nra = FALSE;
|
|
Packit |
fd8b60 |
mkey_convert = FALSE;
|
|
Packit |
fd8b60 |
log_ctx = util_context->kdblog_context;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Parse the qualifiers.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
for (aindex = 1; aindex < argc; aindex++) {
|
|
Packit |
fd8b60 |
if (!strcmp(argv[aindex], "-b7")) {
|
|
Packit |
fd8b60 |
dump = &beta7_version;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-ov")) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("OV dump format not supported\n"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-r13")) {
|
|
Packit |
fd8b60 |
dump = &r1_3_version;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-r18")) {
|
|
Packit |
fd8b60 |
dump = &r1_8_version;
|
|
Packit |
fd8b60 |
} else if (!strncmp(argv[aindex], "-i", 2)) {
|
|
Packit |
fd8b60 |
if (log_ctx && log_ctx->iproprole) {
|
|
Packit |
fd8b60 |
/* ipropx_version is the maximum version acceptable. */
|
|
Packit |
fd8b60 |
ipropx_version = atoi(argv[aindex] + 2);
|
|
Packit |
fd8b60 |
dump = ipropx_version ? &ipropx_1_version : &iprop_version;
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* dump_sno is used to indicate if the serial number should be
|
|
Packit |
fd8b60 |
* populated in the output file to be used later by iprop for
|
|
Packit |
fd8b60 |
* updating the replica's update log when loading.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
dump_sno = TRUE;
|
|
Packit |
fd8b60 |
/* FLAG_OMIT_NRA is set to indicate that non-replicated
|
|
Packit |
fd8b60 |
* attributes should be omitted. */
|
|
Packit |
fd8b60 |
args.omit_nra = TRUE;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("Iprop not enabled\n"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-c")) {
|
|
Packit |
fd8b60 |
conditional = 1;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-verbose")) {
|
|
Packit |
fd8b60 |
args.verbose = TRUE;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-mkey_convert")) {
|
|
Packit |
fd8b60 |
mkey_convert = 1;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-new_mkey_file")) {
|
|
Packit |
fd8b60 |
new_mkey_file = argv[++aindex];
|
|
Packit |
fd8b60 |
mkey_convert = 1;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-rev")) {
|
|
Packit |
fd8b60 |
iterflags |= KRB5_DB_ITER_REV;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-recurse")) {
|
|
Packit |
fd8b60 |
iterflags |= KRB5_DB_ITER_RECURSE;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
args.names = NULL;
|
|
Packit |
fd8b60 |
args.nnames = 0;
|
|
Packit |
fd8b60 |
if (aindex < argc) {
|
|
Packit |
fd8b60 |
ofile = argv[aindex];
|
|
Packit |
fd8b60 |
aindex++;
|
|
Packit |
fd8b60 |
if (aindex < argc) {
|
|
Packit |
fd8b60 |
args.names = &argv[aindex];
|
|
Packit |
fd8b60 |
args.nnames = argc - aindex;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* If a conditional ipropx dump we check if the existing dump is
|
|
Packit |
fd8b60 |
* good enough. */
|
|
Packit |
fd8b60 |
if (ofile != NULL && conditional) {
|
|
Packit |
fd8b60 |
if (!dump->iprop) {
|
|
Packit |
fd8b60 |
com_err(progname, 0,
|
|
Packit |
fd8b60 |
_("Conditional dump is an undocumented option for "
|
|
Packit |
fd8b60 |
"use only for iprop dumps"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (current_dump_sno_in_ulog(util_context, ofile))
|
|
Packit |
fd8b60 |
return;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Make sure the database is open. The policy database only has
|
|
Packit |
fd8b60 |
* to be opened if we try a dump that uses it.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
if (!dbactive) {
|
|
Packit |
fd8b60 |
com_err(progname, 0, _("Database not currently opened!"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* If we're doing a master key conversion, set up for it.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
if (mkey_convert) {
|
|
Packit |
fd8b60 |
if (!valid_master_key) {
|
|
Packit |
fd8b60 |
/* TRUE here means read the keyboard, but only once */
|
|
Packit |
fd8b60 |
retval = krb5_db_fetch_mkey(util_context, master_princ,
|
|
Packit |
fd8b60 |
master_keyblock.enctype, TRUE, FALSE,
|
|
Packit |
fd8b60 |
NULL, NULL, NULL, &master_keyblock);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
com_err(progname, retval, _("while reading master key"));
|
|
Packit |
fd8b60 |
exit(1);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
retval = krb5_db_fetch_mkey_list(util_context, master_princ,
|
|
Packit |
fd8b60 |
&master_keyblock);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
com_err(progname, retval, _("while verifying master key"));
|
|
Packit |
fd8b60 |
exit(1);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
new_master_keyblock.enctype = global_params.enctype;
|
|
Packit |
fd8b60 |
if (new_master_keyblock.enctype == ENCTYPE_UNKNOWN)
|
|
Packit |
fd8b60 |
new_master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (new_mkey_file) {
|
|
Packit |
fd8b60 |
if (global_params.mask & KADM5_CONFIG_KVNO)
|
|
Packit |
fd8b60 |
kt_kvno = global_params.kvno;
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
kt_kvno = IGNORE_VNO;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = krb5_db_fetch_mkey(util_context, master_princ,
|
|
Packit |
fd8b60 |
new_master_keyblock.enctype, FALSE,
|
|
Packit |
fd8b60 |
FALSE, new_mkey_file, &kt_kvno, NULL,
|
|
Packit |
fd8b60 |
&new_master_keyblock);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
com_err(progname, retval, _("while reading new master key"));
|
|
Packit |
fd8b60 |
exit(1);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
printf(_("Please enter new master key....\n"));
|
|
Packit |
fd8b60 |
retval = krb5_db_fetch_mkey(util_context, master_princ,
|
|
Packit |
fd8b60 |
new_master_keyblock.enctype, TRUE,
|
|
Packit |
fd8b60 |
TRUE, NULL, NULL, NULL,
|
|
Packit |
fd8b60 |
&new_master_keyblock);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
com_err(progname, retval, _("while reading new master key"));
|
|
Packit |
fd8b60 |
exit(1);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
/* Get new master key vno that will be used to protect princs. */
|
|
Packit |
fd8b60 |
new_mkvno = get_next_kvno(util_context, master_entry);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (ofile != NULL && strcmp(ofile, "-")) {
|
|
Packit |
fd8b60 |
/* Discourage accidental dumping to filenames beginning with '-'. */
|
|
Packit |
fd8b60 |
if (ofile[0] == '-')
|
|
Packit |
fd8b60 |
usage();
|
|
Packit |
fd8b60 |
if (!prep_ok_file(util_context, ofile, &ok_fd))
|
|
Packit |
fd8b60 |
return; /* prep_ok_file() bumps exit_status */
|
|
Packit |
fd8b60 |
f = create_ofile(ofile, &tmpofile);
|
|
Packit |
fd8b60 |
if (f == NULL) {
|
|
Packit |
fd8b60 |
com_err(progname, errno, _("while opening %s for writing"), ofile);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
f = stdout;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
args.ofile = f;
|
|
Packit |
fd8b60 |
args.context = util_context;
|
|
Packit |
fd8b60 |
args.dump = dump;
|
|
Packit |
fd8b60 |
fprintf(args.ofile, "%s", dump->header);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (dump_sno) {
|
|
Packit |
fd8b60 |
ret = ulog_get_last(util_context, &last);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while reading update log header"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (ipropx_version)
|
|
Packit |
fd8b60 |
fprintf(f, " %u", IPROPX_VERSION);
|
|
Packit |
fd8b60 |
fprintf(f, " %u", last.last_sno);
|
|
Packit |
fd8b60 |
fprintf(f, " %u", last.last_time.seconds);
|
|
Packit |
fd8b60 |
fprintf(f, " %u", last.last_time.useconds);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (dump->header[strlen(dump->header)-1] != '\n')
|
|
Packit |
fd8b60 |
fputc('\n', args.ofile);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_db_iterate(util_context, NULL, dump_iterator, &args, iterflags);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("performing %s dump"), dump->name);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Don't dump policies if specific principal entries were requested. */
|
|
Packit |
fd8b60 |
if (dump->dump_policy != NULL && args.nnames == 0) {
|
|
Packit |
fd8b60 |
ret = krb5_db_iter_policy(util_context, "*", dump->dump_policy, &args);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("performing %s dump"), dump->name);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (f != stdout) {
|
|
Packit |
fd8b60 |
fclose(f);
|
|
Packit |
fd8b60 |
finish_ofile(ofile, &tmpofile);
|
|
Packit |
fd8b60 |
update_ok_file(util_context, ok_fd);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
error:
|
|
Packit |
fd8b60 |
if (tmpofile != NULL)
|
|
Packit |
fd8b60 |
unlink(tmpofile);
|
|
Packit |
fd8b60 |
free(tmpofile);
|
|
Packit |
fd8b60 |
exit_status++;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Restore the database from any version dump file. */
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
restore_dump(krb5_context context, char *dumpfile, FILE *f,
|
|
Packit |
fd8b60 |
krb5_boolean verbose, dump_version *dump)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int err = 0;
|
|
Packit |
fd8b60 |
int lineno = 1;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Process the records. */
|
|
Packit |
fd8b60 |
while (!(err = dump->load_record(context, dumpfile, f, verbose, &lineno)));
|
|
Packit |
fd8b60 |
if (err != -1) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: error processing line %d of %s\n"), progname,
|
|
Packit |
fd8b60 |
lineno, dumpfile);
|
|
Packit |
fd8b60 |
return err;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Usage: load_db [-b7] [-r13] [-r18] [-verbose] [-update] [-hash] filename
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
void
|
|
Packit |
fd8b60 |
load_db(int argc, char **argv)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
FILE *f = NULL;
|
|
Packit |
fd8b60 |
char *dumpfile = NULL, *dbname, buf[BUFSIZ];
|
|
Packit |
fd8b60 |
dump_version *load = NULL;
|
|
Packit |
fd8b60 |
int aindex;
|
|
Packit |
fd8b60 |
kdb_log_context *log_ctx;
|
|
Packit |
fd8b60 |
kdb_last_t last;
|
|
Packit |
fd8b60 |
krb5_boolean db_locked = FALSE, temp_db_created = FALSE;
|
|
Packit |
fd8b60 |
krb5_boolean verbose = FALSE, update = FALSE, iprop_load = FALSE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Parse the arguments. */
|
|
Packit |
fd8b60 |
dbname = global_params.dbname;
|
|
Packit |
fd8b60 |
exit_status = 0;
|
|
Packit |
fd8b60 |
log_ctx = util_context->kdblog_context;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (aindex = 1; aindex < argc; aindex++) {
|
|
Packit |
fd8b60 |
if (!strcmp(argv[aindex], "-b7")){
|
|
Packit |
fd8b60 |
load = &beta7_version;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-ov")) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("OV dump format not supported\n"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-r13")) {
|
|
Packit |
fd8b60 |
load = &r1_3_version;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-r18")){
|
|
Packit |
fd8b60 |
load = &r1_8_version;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-i")) {
|
|
Packit |
fd8b60 |
if (log_ctx && log_ctx->iproprole) {
|
|
Packit |
fd8b60 |
load = &iprop_version;
|
|
Packit |
fd8b60 |
iprop_load = TRUE;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("Iprop not enabled\n"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-verbose")) {
|
|
Packit |
fd8b60 |
verbose = TRUE;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-update")){
|
|
Packit |
fd8b60 |
update = TRUE;
|
|
Packit |
fd8b60 |
} else if (!strcmp(argv[aindex], "-hash")) {
|
|
Packit |
fd8b60 |
if (!add_db_arg("hash=true")) {
|
|
Packit |
fd8b60 |
com_err(progname, ENOMEM, _("while parsing options"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (argc - aindex != 1)
|
|
Packit |
fd8b60 |
usage();
|
|
Packit |
fd8b60 |
dumpfile = argv[aindex];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Open the dumpfile. */
|
|
Packit |
fd8b60 |
if (dumpfile != NULL) {
|
|
Packit |
fd8b60 |
f = fopen(dumpfile, "r");
|
|
Packit |
fd8b60 |
if (f == NULL) {
|
|
Packit |
fd8b60 |
com_err(progname, errno, _("while opening %s"), dumpfile);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
f = stdin;
|
|
Packit |
fd8b60 |
dumpfile = _("standard input");
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Auto-detect dump version if we weren't told, or verify if we were. */
|
|
Packit |
fd8b60 |
if (fgets(buf, sizeof(buf), f) == NULL) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: can't read dump header in %s\n"), progname,
|
|
Packit |
fd8b60 |
dumpfile);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (load) {
|
|
Packit |
fd8b60 |
/* Only check what we know; some headers only contain a prefix.
|
|
Packit |
fd8b60 |
* NB: this should work for ipropx even though load is iprop */
|
|
Packit |
fd8b60 |
if (strncmp(buf, load->header, strlen(load->header)) != 0) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: dump header bad in %s\n"), progname,
|
|
Packit |
fd8b60 |
dumpfile);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
if (strcmp(buf, beta7_version.header) == 0) {
|
|
Packit |
fd8b60 |
load = &beta7_version;
|
|
Packit |
fd8b60 |
} else if (strcmp(buf, r1_3_version.header) == 0) {
|
|
Packit |
fd8b60 |
load = &r1_3_version;
|
|
Packit |
fd8b60 |
} else if (strcmp(buf, r1_8_version.header) == 0) {
|
|
Packit |
fd8b60 |
load = &r1_8_version;
|
|
Packit |
fd8b60 |
} else if (strcmp(buf, r1_11_version.header) == 0) {
|
|
Packit |
fd8b60 |
load = &r1_11_version;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: dump header bad in %s\n"), progname,
|
|
Packit |
fd8b60 |
dumpfile);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (global_params.iprop_enabled &&
|
|
Packit |
fd8b60 |
ulog_map(util_context, global_params.iprop_logfile,
|
|
Packit |
fd8b60 |
global_params.iprop_ulogsize)) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("Could not open iprop ulog\n"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (load->updateonly && !update) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: dump version %s can only be loaded with the "
|
|
Packit |
fd8b60 |
"-update flag\n"), progname, load->name);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* If we are not in update mode, we create an alternate database and then
|
|
Packit |
fd8b60 |
* promote it to be the live db. */
|
|
Packit |
fd8b60 |
if (!update) {
|
|
Packit |
fd8b60 |
if (!add_db_arg("temporary")) {
|
|
Packit |
fd8b60 |
com_err(progname, ENOMEM, _("computing parameters for database"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (iprop_load && !add_db_arg("merge_nra")) {
|
|
Packit |
fd8b60 |
com_err(progname, ENOMEM, _("computing parameters for database"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_db_create(util_context, db5util_db_args);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while creating database"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
temp_db_created = TRUE;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
/* Initialize the database. */
|
|
Packit |
fd8b60 |
ret = krb5_db_open(util_context, db5util_db_args,
|
|
Packit |
fd8b60 |
KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while opening database"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Make sure the db is left unusable if the update fails, if the db
|
|
Packit |
fd8b60 |
* supports locking. */
|
|
Packit |
fd8b60 |
ret = krb5_db_lock(util_context, KRB5_DB_LOCKMODE_PERMANENT);
|
|
Packit |
fd8b60 |
if (ret == 0) {
|
|
Packit |
fd8b60 |
db_locked = TRUE;
|
|
Packit |
fd8b60 |
} else if (ret != KRB5_PLUGIN_OP_NOTSUPP) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while permanently locking database"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (log_ctx != NULL && log_ctx->iproprole && !update) {
|
|
Packit |
fd8b60 |
/* Don't record updates we are making to the temporary DB. We will
|
|
Packit |
fd8b60 |
* reinitialize or update the ulog header after promoting it. */
|
|
Packit |
fd8b60 |
log_ctx->iproprole = IPROP_REPLICA;
|
|
Packit |
fd8b60 |
if (iprop_load) {
|
|
Packit |
fd8b60 |
/* Parse the iprop header information. */
|
|
Packit |
fd8b60 |
if (!parse_iprop_header(buf, &load, &last))
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (restore_dump(util_context, dumpfile ? dumpfile : _("standard input"),
|
|
Packit |
fd8b60 |
f, verbose, load)) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: %s restore failed\n"), progname, load->name);
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (db_locked && (ret = krb5_db_unlock(util_context))) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while unlocking database"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (!update) {
|
|
Packit |
fd8b60 |
/* Initialize the ulog header before promoting so we can't leave behind
|
|
Packit |
fd8b60 |
* the pre-load ulog state if we are killed just after promoting. */
|
|
Packit |
fd8b60 |
if (log_ctx != NULL && log_ctx->iproprole) {
|
|
Packit |
fd8b60 |
ret = ulog_init_header(util_context);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while reinitializing update log"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_db_promote(util_context, db5util_db_args);
|
|
Packit |
fd8b60 |
/* Ignore a not supported error since there is nothing to do about it
|
|
Packit |
fd8b60 |
* anyway. */
|
|
Packit |
fd8b60 |
if (ret != 0 && ret != KRB5_PLUGIN_OP_NOTSUPP) {
|
|
Packit |
fd8b60 |
com_err(progname, ret,
|
|
Packit |
fd8b60 |
_("while making newly loaded database live"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (log_ctx != NULL && log_ctx->iproprole) {
|
|
Packit |
fd8b60 |
/* Reinitialize the ulog header since we replaced the DB, and
|
|
Packit |
fd8b60 |
* record the iprop state if we received it. */
|
|
Packit |
fd8b60 |
ret = ulog_init_header(util_context);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while reinitializing update log"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (iprop_load) {
|
|
Packit |
fd8b60 |
ret = ulog_set_last(util_context, &last);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(progname, ret,
|
|
Packit |
fd8b60 |
_("while writing update log header"));
|
|
Packit |
fd8b60 |
goto error;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
/* If we created a temporary DB but didn't succeed, destroy it. */
|
|
Packit |
fd8b60 |
if (exit_status && temp_db_created) {
|
|
Packit |
fd8b60 |
ret = krb5_db_destroy(util_context, db5util_db_args);
|
|
Packit |
fd8b60 |
/* Ignore a not supported error since there is nothing to do about
|
|
Packit |
fd8b60 |
* it anyway. */
|
|
Packit |
fd8b60 |
if (ret != 0 && ret != KRB5_PLUGIN_OP_NOTSUPP) {
|
|
Packit |
fd8b60 |
com_err(progname, ret, _("while deleting bad database %s"),
|
|
Packit |
fd8b60 |
dbname);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (f != NULL && f != stdin)
|
|
Packit |
fd8b60 |
fclose(f);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
error:
|
|
Packit |
fd8b60 |
exit_status++;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|