krb5 commit [krb5-1.12]: Fix compatibility with pre-1.11 iprop dump files
Tom Yu
tlyu at mit.edu
Wed Dec 9 17:58:17 EST 2015
https://github.com/krb5/krb5/commit/04709a3184e01b5ef23605082034cfbd073a9c70
commit 04709a3184e01b5ef23605082034cfbd073a9c70
Author: Greg Hudson <ghudson at mit.edu>
Date: Fri Jul 17 13:03:35 2015 -0400
Fix compatibility with pre-1.11 iprop dump files
Ticket #7223 added new policy fields and a new dump format version to
marshal them, but did not add a new iprop dump format version. As a
result, slave KDCs running 1.11 or later cannot receive full resyncs
from master KDCs running 1.10 or earlier. (Reported by John
Devitofranceschi.)
Retroactively add support for pre-1.11 policy entries by making
process_r1_11_policy() read the first ten fields, check whether the
next whitespace character is a newline, and then read the rest if it
is not.
(back ported from commit 3c9ab5220bcc3f57641f6f4b6942b17aadb6613d)
(cherry picked from commit 6f1b25097969b4685263639a5214d440ce233793)
ticket: 8317 (new)
version_fixed: 1.12.5
status: resolved
src/kadmin/dbutil/dump.c | 58 +++++++++++++++++++++++++++++++---------------
src/tests/t_dump.py | 12 +++++++--
2 files changed, 48 insertions(+), 22 deletions(-)
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
index d4e8090..e64e860 100644
--- a/src/kadmin/dbutil/dump.c
+++ b/src/kadmin/dbutil/dump.c
@@ -959,41 +959,61 @@ process_r1_11_policy(krb5_context context, const char *fname, FILE *filep,
char namebuf[1024];
char keysaltbuf[KRB5_KDB_MAX_ALLOWED_KS_LEN + 1];
unsigned int refcnt;
- int nread, ret = 0;
+ int nread, c, ret = 0;
memset(&rec, 0, sizeof(rec));
(*linenop)++;
rec.name = namebuf;
- rec.allowed_keysalts = keysaltbuf;
- nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t"
- "%u\t%u\t%u\t"
- K5CONST_WIDTH_SCANF_STR(KRB5_KDB_MAX_ALLOWED_KS_LEN)
- "\t%hd", rec.name, &rec.pw_min_life, &rec.pw_max_life,
+ /*
+ * Due to a historical error, iprop dumps use the same version before and
+ * after the 1.11 policy extensions. So we need to accept both 1.8-format
+ * and 1.11-format policy entries. Begin by reading the 1.8 fields.
+ */
+ nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
+ rec.name, &rec.pw_min_life, &rec.pw_max_life,
&rec.pw_min_length, &rec.pw_min_classes,
&rec.pw_history_num, &refcnt, &rec.pw_max_fail,
- &rec.pw_failcnt_interval, &rec.pw_lockout_duration,
- &rec.attributes, &rec.max_life, &rec.max_renewable_life,
- rec.allowed_keysalts, &rec.n_tl_data);
+ &rec.pw_failcnt_interval, &rec.pw_lockout_duration);
if (nread == EOF)
return -1;
- if (nread != 15) {
+ if (nread != 10) {
fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
return 1;
}
- if (rec.allowed_keysalts && !strcmp(rec.allowed_keysalts, "-"))
- rec.allowed_keysalts = NULL;
+ /* The next character should be a newline (1.8) or a tab (1.11). */
+ c = getc(filep);
+ if (c == EOF)
+ return -1;
+ if (c != '\n') {
+ /* Read the additional 1.11-format fields. */
+ rec.allowed_keysalts = keysaltbuf;
+ nread = fscanf(filep, "%u\t%u\t%u\t"
+ K5CONST_WIDTH_SCANF_STR(KRB5_KDB_MAX_ALLOWED_KS_LEN)
+ "\t%hd", &rec.attributes, &rec.max_life,
+ &rec.max_renewable_life, rec.allowed_keysalts,
+ &rec.n_tl_data);
+ if (nread == EOF)
+ return -1;
+ if (nread != 5) {
+ fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
+ return 1;
+ }
- /* Get TL data */
- ret = alloc_tl_data(rec.n_tl_data, &rec.tl_data);
- if (ret)
- goto cleanup;
+ if (rec.allowed_keysalts && !strcmp(rec.allowed_keysalts, "-"))
+ rec.allowed_keysalts = NULL;
- ret = process_tl_data(fname, filep, *linenop, rec.tl_data);
- if (ret)
- goto cleanup;
+ /* Get TL data */
+ ret = alloc_tl_data(rec.n_tl_data, &rec.tl_data);
+ if (ret)
+ goto cleanup;
+
+ ret = process_tl_data(fname, filep, *linenop, rec.tl_data);
+ if (ret)
+ goto cleanup;
+ }
ret = krb5_db_create_policy(context, &rec);
if (ret)
diff --git a/src/tests/t_dump.py b/src/tests/t_dump.py
index edf7a23..42f8f0e 100644
--- a/src/tests/t_dump.py
+++ b/src/tests/t_dump.py
@@ -12,12 +12,15 @@ realm.run_kadminl('addpol fred')
dumpfile = os.path.join(realm.testdir, 'dump')
realm.run([kdb5_util, 'dump', dumpfile])
-# Write an additional policy record to the dump.
+# Write additional policy records to the dump. Use the 1.8 format for
+# one of them, to test retroactive compatibility (for issue #8213).
f = open('testdir/dump', 'a')
+f.write('policy compat 0 0 3 4 5 0 '
+ '0 0 0\n')
f.write('policy barney 0 0 1 1 1 0 '
'0 0 0 0 0 0 - 1 '
'2 28 '
- 'fd100f5064625f6372656174696f6e404b5242544553542e434f4d00')
+ 'fd100f5064625f6372656174696f6e404b5242544553542e434f4d00\n')
f.close()
# Destroy and load the database; check that the policies exist.
@@ -33,6 +36,9 @@ if 'Expiration date: [never]' not in out or 'MKey: vno 1' not in out:
out = realm.run_kadminl('getpols')
if 'fred\n' not in out or 'barney\n' not in out:
fail('Missing policy after load')
+out = realm.run_kadminl('getpol compat')
+if 'Number of old keys kept: 5' not in out:
+ fail('Policy (1.8 format) has wrong value after load')
out = realm.run_kadminl('getpol barney')
if 'Number of old keys kept: 1' not in out:
fail('Policy has wrong value after load')
@@ -44,7 +50,7 @@ out = realm.run_kadminl('getprincs')
if realm.user_princ not in out or realm.host_princ not in out:
fail('Missing principal after load')
out = realm.run_kadminl('getpols')
-if 'fred\n' not in out or 'barney\n' not in out:
+if 'compat\n' not in out or 'fred\n' not in out or 'barney\n' not in out:
fail('Missing policy after second load')
srcdumpdir = os.path.join(srctop, 'tests', 'dumpfiles')
More information about the cvs-krb5
mailing list