diff options
author | Greg Hudson <ghudson@mit.edu> | 2015-07-17 13:03:35 -0400 |
---|---|---|
committer | Tom Yu <tlyu@mit.edu> | 2015-12-02 13:36:53 -0500 |
commit | 6f1b25097969b4685263639a5214d440ce233793 (patch) | |
tree | 53048db04a2d1bdad37d70e810d1033af206deaa | |
parent | d6d860410216c3e3186025b7ea4eb5f53643fa38 (diff) | |
download | krb5-6f1b25097969b4685263639a5214d440ce233793.zip krb5-6f1b25097969b4685263639a5214d440ce233793.tar.gz krb5-6f1b25097969b4685263639a5214d440ce233793.tar.bz2 |
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)
ticket: 8286 (new)
version_fixed: 1.13.3
status: resolved
-rw-r--r-- | src/kadmin/dbutil/dump.c | 58 | ||||
-rw-r--r-- | 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 bfb8577..07f62e9 100644 --- a/src/kadmin/dbutil/dump.c +++ b/src/kadmin/dbutil/dump.c @@ -958,41 +958,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') |