svn rev #21830: branches/mkey_migrate/src/ kadmin/dbutil/ lib/kadm5/srv/
raeburn@MIT.EDU
raeburn at MIT.EDU
Thu Jan 29 15:29:01 EST 2009
http://src.mit.edu/fisheye/changelog/krb5/?cs=21830
Commit By: raeburn
Log Message:
Implement "kdb5_util update_princ_encryption".
Duplicates glob-to-regexp code from libkadm5srv for now (noted in
comments in both places).
Updated kdb5_util.M for update_princ_encryption, and added
placeholders for add_mkey, use_mkey, and list_mkeys.
Changed Files:
U branches/mkey_migrate/src/kadmin/dbutil/dump.c
U branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c
U branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.M
U branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.c
U branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h
U branches/mkey_migrate/src/lib/kadm5/srv/svr_iters.c
Modified: branches/mkey_migrate/src/kadmin/dbutil/dump.c
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/dump.c 2009-01-29 19:54:21 UTC (rev 21829)
+++ branches/mkey_migrate/src/kadmin/dbutil/dump.c 2009-01-29 20:28:58 UTC (rev 21830)
@@ -1,7 +1,7 @@
/*
* kadmin/dbutil/dump.c
*
- * Copyright 1990,1991,2001,2006,2008 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991,2001,2006,2008,2009 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -46,8 +46,8 @@
* Needed for master key conversion.
*/
static int mkey_convert;
-static krb5_keyblock new_master_keyblock;
-static krb5_kvno new_mkvno;
+krb5_keyblock new_master_keyblock;
+krb5_kvno new_mkvno;
static int backwards;
static int recursive;
@@ -179,7 +179,6 @@
extern int exit_status;
extern krb5_context util_context;
extern kadm5_config_params global_params;
-extern krb5_keylist_node *master_keylist;
extern krb5_db_entry master_entry;
/* Strings */
@@ -263,7 +262,7 @@
/*
* Re-encrypt the key_data with the new master key...
*/
-static krb5_error_code master_key_convert(context, db_entry)
+krb5_error_code master_key_convert(context, db_entry)
krb5_context context;
krb5_db_entry * db_entry;
{
@@ -316,6 +315,7 @@
}
*key_data = new_key_data;
}
+ assert(new_mkvno > 0);
retval = krb5_dbe_update_mkvno(context, db_entry, new_mkvno);
if (retval)
return retval;
Modified: branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c 2009-01-29 19:54:21 UTC (rev 21829)
+++ branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c 2009-01-29 20:28:58 UTC (rev 21830)
@@ -1,3 +1,4 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -12,6 +13,22 @@
#include <adm_proto.h>
#include "kdb5_util.h"
+#if defined(HAVE_COMPILE) && defined(HAVE_STEP)
+#define SOLARIS_REGEXPS
+#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC)
+#define POSIX_REGEXPS
+#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC)
+#define BSD_REGEXPS
+#else
+#error I cannot find any regexp functions
+#endif
+#ifdef SOLARIS_REGEXPS
+#include <regexpr.h>
+#endif
+#ifdef POSIX_REGEXPS
+#include <regex.h>
+#endif
+
extern krb5_keyblock master_keyblock; /* current mkey */
extern krb5_principal master_princ;
extern krb5_keylist_node *master_keylist;
@@ -292,7 +309,7 @@
return;
}
- retval = add_new_mkey(util_context, &master_entry, &new_mkeyblock, NULL);
+ retval = add_new_mkey(util_context, &master_entry, &new_mkeyblock, 0);
if (retval) {
com_err(progname, retval, "adding new master key to master principal");
exit_status++;
@@ -674,3 +691,354 @@
}
return;
}
+
+struct update_enc_mkvno {
+ unsigned int re_match_count;
+ unsigned int already_current;
+ unsigned int updated;
+#ifdef SOLARIS_REGEXPS
+ char *expbuf;
+#endif
+#ifdef POSIX_REGEXPS
+ regex_t preg;
+#endif
+#if !defined(SOLARIS_REGEXPS) && !defined(POSIX_REGEXPS)
+ unsigned char placeholder;
+#endif
+};
+
+/* XXX Duplicated in libkadm5srv! */
+/*
+ * Function: glob_to_regexp
+ *
+ * Arguments:
+ *
+ * glob (r) the shell-style glob (?*[]) to convert
+ * realm (r) the default realm to append, or NULL
+ * regexp (w) the ed-style regexp created from glob
+ *
+ * Effects:
+ *
+ * regexp is filled in with allocated memory contained a regular
+ * expression to be used with re_comp/compile that matches what the
+ * shell-style glob would match. If glob does not contain an "@"
+ * character and realm is not NULL, "@*" is appended to the regexp.
+ *
+ * Conversion algorithm:
+ *
+ * quoted characters are copied quoted
+ * ? is converted to .
+ * * is converted to .*
+ * active characters are quoted: ^, $, .
+ * [ and ] are active but supported and have the same meaning, so
+ * they are copied
+ * other characters are copied
+ * regexp is anchored with ^ and $
+ */
+static int glob_to_regexp(char *glob, char *realm, char **regexp)
+{
+ int append_realm;
+ char *p;
+
+ /* validate the glob */
+ if (glob[strlen(glob)-1] == '\\')
+ return EINVAL;
+
+ /* A character of glob can turn into two in regexp, plus ^ and $ */
+ /* and trailing null. If glob has no @, also allocate space for */
+ /* the realm. */
+ append_realm = (realm != NULL) && (strchr(glob, '@') == NULL);
+ p = (char *) malloc(strlen(glob)*2+ 3 + (append_realm ? 3 : 0));
+ if (p == NULL)
+ return ENOMEM;
+ *regexp = p;
+
+ *p++ = '^';
+ while (*glob) {
+ switch (*glob) {
+ case '?':
+ *p++ = '.';
+ break;
+ case '*':
+ *p++ = '.';
+ *p++ = '*';
+ break;
+ case '.':
+ case '^':
+ case '$':
+ *p++ = '\\';
+ *p++ = *glob;
+ break;
+ case '\\':
+ *p++ = '\\';
+ *p++ = *++glob;
+ break;
+ default:
+ *p++ = *glob;
+ break;
+ }
+ glob++;
+ }
+
+ if (append_realm) {
+ *p++ = '@';
+ *p++ = '.';
+ *p++ = '*';
+ }
+
+ *p++ = '$';
+ *p++ = '\0';
+ return 0;
+}
+
+static int
+update_princ_encryption_1(void *cb, krb5_db_entry *ent)
+{
+ struct update_enc_mkvno *p = cb;
+ char *pname = 0;
+ krb5_error_code retval;
+ int match;
+ krb5_timestamp now;
+ int nentries = 1;
+ int result;
+ krb5_kvno old_mkvno;
+
+ retval = krb5_unparse_name(util_context, ent->princ, &pname);
+ if (retval) {
+ com_err(progname, retval,
+ "getting string representation of principal name");
+ goto fail;
+ }
+
+ if (krb5_principal_compare (util_context, ent->princ, master_princ)) {
+ goto skip;
+ }
+
+#ifdef SOLARIS_REGEXPS
+ match = (step(pname, p->expbuf) != 0);
+#endif
+#ifdef POSIX_REGEXPS
+ match = (regexec(&p->preg, pname, 0, NULL, 0) == 0);
+#endif
+#ifdef BSD_REGEXPS
+ match = (re_exec(pname) != 0);
+#endif
+ if (!match) {
+ goto skip;
+ }
+ p->re_match_count++;
+ retval = krb5_dbe_lookup_mkvno(util_context, ent, &old_mkvno);
+ if (retval) {
+ com_err(progname, retval,
+ "determining master key used for principal '%s'",
+ pname);
+ goto fail;
+ }
+ if (old_mkvno == new_mkvno) {
+ p->already_current++;
+ goto skip;
+ }
+ retval = master_key_convert (util_context, ent);
+ if (retval) {
+ com_err(progname, retval,
+ "error re-encrypting key for principal '%s'", pname);
+ goto fail;
+ }
+ if ((retval = krb5_timeofday(util_context, &now))) {
+ com_err(progname, retval, "while getting current time");
+ goto fail;
+ }
+
+ if ((retval = krb5_dbe_update_mod_princ_data(util_context, ent,
+ now, master_princ))) {
+ com_err(progname, retval,
+ "while updating principal '%s' modification time", pname);
+ goto fail;
+ }
+
+ if ((retval = krb5_db_put_principal(util_context, ent, &nentries))) {
+ com_err(progname, retval,
+ "while updating principal '%s' key data in the database",
+ pname);
+ goto fail;
+ }
+ p->updated++;
+skip:
+ result = 0;
+ goto egress;
+fail:
+ exit_status++;
+ result = 1;
+egress:
+ if (pname)
+ krb5_free_unparsed_name(util_context, pname);
+ return result;
+}
+
+extern int are_you_sure (const char *, ...)
+#if !defined(__cplusplus) && (__GNUC__ > 2)
+ __attribute__((__format__(__printf__, 1, 2)))
+#endif
+ ;
+
+int
+are_you_sure (const char *format, ...)
+{
+ va_list va;
+ char ansbuf[100];
+
+ va_start(va, format);
+ vprintf(format, va);
+ va_end(va);
+ printf("\n(type 'yes' to confirm)? ");
+ fflush(stdout);
+ if (fgets(ansbuf, sizeof(ansbuf), stdin) == NULL)
+ return 0;
+ if (strcmp(ansbuf, "yes\n"))
+ return 0;
+ return 1;
+}
+
+void
+kdb5_update_princ_encryption(int argc, char *argv[])
+{
+ struct update_enc_mkvno data = { 0 };
+ char *name_pattern = NULL;
+ int force = 0;
+ int optchar;
+ krb5_error_code retval;
+ krb5_actkvno_node *actkvno_list;
+ krb5_db_entry master_entry;
+ int nentries = 1, more = 0;
+ char *mkey_fullname = 0;
+#ifdef BSD_REGEXPS
+ char *msg;
+#endif
+ char *regexp = NULL;
+ krb5_keyblock *tmp_keyblock = NULL;
+
+ while ((optchar = getopt(argc, argv, "f")) != -1) {
+ switch (optchar) {
+ case 'f':
+ force = 1;
+ break;
+ case '?':
+ case ':':
+ default:
+ usage();
+ }
+ }
+ if (argv[optind] != NULL) {
+ name_pattern = argv[optind];
+ if (argv[optind+1] != NULL)
+ usage();
+ }
+
+ retval = krb5_unparse_name(util_context, master_princ, &mkey_fullname);
+ if (retval) {
+ com_err(progname, retval, "while formatting master principal name");
+ exit_status++;
+ goto cleanup;
+ }
+
+ if (master_keylist == NULL) {
+ com_err(progname, retval, "master keylist not initialized");
+ exit_status++;
+ goto cleanup;
+ }
+
+ /* The glob_to_regexp code only cares if the "realm" parameter is
+ NULL or not; the string data is irrelevant. */
+ if (name_pattern == NULL)
+ name_pattern = "*";
+ if (glob_to_regexp(name_pattern, "hi", ®exp) != 0) {
+ com_err(progname, ENOMEM,
+ "converting glob pattern '%s' to regular expression",
+ name_pattern);
+ exit_status++;
+ goto cleanup;
+ }
+
+ if (
+#ifdef SOLARIS_REGEXPS
+ ((data.expbuf = compile(regexp, NULL, NULL)) == NULL)
+#endif
+#ifdef POSIX_REGEXPS
+ ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0)
+#endif
+#ifdef BSD_REGEXPS
+ ((msg = (char *) re_comp(regexp)) != NULL)
+#endif
+ )
+ {
+ /* XXX syslog msg or regerr(regerrno) */
+ com_err(progname, 0, "error compiling converted regexp '%s'", regexp);
+ free(regexp);
+ exit_status++;
+ goto cleanup;
+ }
+
+ retval = krb5_db_get_principal(util_context, master_princ, &master_entry,
+ &nentries, &more);
+ if (retval != 0) {
+ com_err(progname, retval, "while getting master key principal %s",
+ mkey_fullname);
+ exit_status++;
+ goto cleanup;
+ }
+ if (nentries != 1) {
+ com_err(progname, 0,
+ "cannot find master key principal %s in database!",
+ mkey_fullname);
+ exit_status++;
+ goto cleanup;
+ }
+
+ retval = krb5_dbe_lookup_actkvno(util_context, &master_entry, &actkvno_list);
+ if (retval != 0) {
+ com_err(progname, retval, "while looking up active kvno list");
+ exit_status++;
+ goto cleanup;
+ }
+
+ /* Master key is always stored encrypted in the latest version of
+ itself. */
+ new_mkvno = krb5_db_get_key_data_kvno(util_context,
+ master_entry.n_key_data,
+ master_entry.key_data);
+
+ retval = krb5_dbe_find_mkey(util_context, master_keylist,
+ &master_entry, &tmp_keyblock);
+ if (retval) {
+ com_err(progname, retval, "retrieving the most recent master key");
+ exit_status++;
+ goto cleanup;
+ }
+ new_master_keyblock = *tmp_keyblock;
+
+ if (!force &&
+ !are_you_sure("Re-encrypt all keys not using master key vno %u?",
+ new_mkvno)) {
+ printf("OK, doing nothing.\n");
+ exit_status++;
+ goto cleanup;
+ }
+
+ retval = krb5_db_iterate(util_context, name_pattern,
+ update_princ_encryption_1, &data);
+ /* If exit_status is set, then update_princ_encryption_1 already
+ printed a message. */
+ if (retval != 0 && exit_status == 0) {
+ com_err(progname, retval, "trying to process principal database");
+ exit_status++;
+ }
+ (void) krb5_db_fini(util_context);
+ printf("%u principals processed: %u updated, %u already current\n",
+ data.re_match_count, data.updated, data.already_current);
+
+cleanup:
+ free(regexp);
+ memset(&new_master_keyblock, 0, sizeof(new_master_keyblock));
+ krb5_free_keyblock(util_context, tmp_keyblock);
+ krb5_free_unparsed_name(util_context, mkey_fullname);
+}
Modified: branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.M
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.M 2009-01-29 19:54:21 UTC (rev 21829)
+++ branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.M 2009-01-29 20:28:58 UTC (rev 21830)
@@ -215,5 +215,24 @@
.TP
\fBark\fP
Adds a random key.
+.TP
+\fBadd_mkey\fP ...
+This option needs documentation.
+.TP
+\fBuse_mkey\fP ...
+This option needs documentation.
+.TP
+\fBlist_mkeys\fP
+This option needs documentation.
+.TP
+\fBupdate_princ_encryption\fP [\fB\-f\fP] [\fBprinc\-pattern\fP]
+Update all principal records (or only those matching the
+.B princ\-pattern
+glob pattern) to re-encrypt the key data using the latest version of
+the database master key, if they are encrypted using older versions.
+If the
+.B \-f
+option is not given, ask for confirmation before starting to make
+changes.
.SH SEE ALSO
kadmin(8)
Modified: branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.c
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.c 2009-01-29 19:54:21 UTC (rev 21829)
+++ branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.c 2009-01-29 20:28:58 UTC (rev 21830)
@@ -1,7 +1,7 @@
/*
* admin/edit/kdb5_edit.c
*
- * (C) Copyright 1990,1991, 1996, 2008 by the Massachusetts Institute of Technology.
+ * (C) Copyright 1990,1991, 1996, 2008, 2009 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -85,7 +85,7 @@
void usage()
{
fprintf(stderr, "Usage: "
- "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n"
+ "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n"
"\t [-kv mkeyVNO] [-sf stashfilename] [-m] cmd [cmd_options]\n"
"\tcreate [-s]\n"
"\tdestroy [-f]\n"
@@ -97,7 +97,9 @@
"\tark [-e etype_list] principal\n"
"\tadd_mkey [-e etype] [-s]\n"
"\tuse_mkey kvno [time]\n"
- "\tlist_mkeys\n");
+ "\tlist_mkeys\n"
+ "\tupdate_princ_encryption [-f] [princ-pattern]\n"
+ );
/* avoid a string length compiler warning */
fprintf(stderr,
"\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
@@ -135,6 +137,7 @@
{"add_mkey", kdb5_add_mkey, 1}, /* 1 is opendb */
{"use_mkey", kdb5_use_mkey, 1}, /* 1 is opendb */
{"list_mkeys", kdb5_list_mkeys, 1}, /* 1 is opendb */
+ {"update_princ_encryption", kdb5_update_princ_encryption, 1},
{NULL, NULL, 0},
};
Modified: branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h 2009-01-29 19:54:21 UTC (rev 21829)
+++ branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h 2009-01-29 20:28:58 UTC (rev 21830)
@@ -1,7 +1,7 @@
/*
* admin/edit/kdb5_edit.h
*
- * Copyright 1992, 2008 by the Massachusetts Institute of Technology.
+ * Copyright 1992, 2008, 2009 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -45,6 +45,9 @@
extern krb5_db_entry master_db;
extern char **db5util_db_args;
extern int db5util_db_args_size;
+extern krb5_kvno new_mkvno;
+extern krb5_keylist_node *master_keylist;
+extern krb5_keyblock new_master_keyblock;
extern int add_db_arg(char *arg);
extern void usage(void);
@@ -83,6 +86,9 @@
extern void kdb5_add_mkey (int argc, char **argv);
extern void kdb5_use_mkey (int argc, char **argv);
extern void kdb5_list_mkeys (int argc, char **argv);
+extern void kdb5_update_princ_encryption (int argc, char **argv);
+extern krb5_error_code master_key_convert(krb5_context context,
+ krb5_db_entry *db_entry);
extern void update_ok_file (char *file_name);
Modified: branches/mkey_migrate/src/lib/kadm5/srv/svr_iters.c
===================================================================
--- branches/mkey_migrate/src/lib/kadm5/srv/svr_iters.c 2009-01-29 19:54:21 UTC (rev 21829)
+++ branches/mkey_migrate/src/lib/kadm5/srv/svr_iters.c 2009-01-29 20:28:58 UTC (rev 21830)
@@ -46,6 +46,7 @@
#endif
};
+/* XXX Duplicated in kdb5_util! */
/*
* Function: glob_to_regexp
*
More information about the cvs-krb5
mailing list