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", &regexp) != 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