Skip Menu |
 

Date: Thu, 27 Dec 2012 13:37:12 -0500
From: Richard Basch <basch@alum.mit.edu>
Subject: krb5-1.11, patch 1 of 4
To: krb5-bugs@mit.edu
Download (untitled) / with headers
text/html 30.4KiB

Message body is not shown because it is too large.

Date: Thu, 27 Dec 2012 22:30:31 -0500
From: Richard Basch <basch@alum.mit.edu>
Subject: RE: [krbdev.mit.edu #7522] AutoReply: krb5-1.11, patch 1 of 4
To: rt@krbdev.mit.edu
RT-Send-Cc:
Download (untitled) / with headers
text/plain 10.6KiB
To summarize the characteristics of the patches...

Patch 1 is clearly a bug fix to a problem in krb5-1.11.
Patch 2 is innocuous with the current code but crucial when patch 3 is
introduced; the original code was inconsistent with the design of the
circular buffer.
Patch 3 makes it easier to promote another slave as a master by tracking
ulog entries. The ulog is in place, so this might be a feature or a bug fix
to support improved failover.

Patch 4 introduces new program arguments/options to support tree-based
replication. This deviates from the goal of having point releases which do
not introduce new features/APIs. Protocol compatibility exists for all
iprop v1 clients. It also introduces the concept of doing an incremental
sync immediately after a full resync to catch up on the transaction log.

Perhaps the portion of patch 4 which does an incremental sync after the full
resync may be considered a bug fix... if so, the following excerpt of patch
4 can be applied separately from the rest of patch 4 [krbdev #7521]:

diff -ru src.03/slave/kpropd.c src.04/slave/kpropd.c
--- src.03/slave/kpropd.c 2012-12-17 21:47:05.000000000 -0500
+++ src.04/slave/kpropd.c 2012-12-25 23:59:41.888938248 -0500
@@ -993,6 +995,15 @@
backoff_time);
}
(void) sleep(backoff_time);
+ } else if (incr_ret && full_ret &&
+ incr_ret->ret == UPDATE_FULL_RESYNC_NEEDED &&
+ full_ret->ret == UPDATE_OK) {
+ /*
+ * Poll immediately after a full resync to ensure we are
+ * up-to-date with any incremental changes received during
+ * the processing of the database transfer & reload.
+ */
+ 1;
} else {
if (debug) {
fprintf(stderr, _("Waiting for %d seconds before checking "


Show quoted text
-----Original Message-----
From: krb5 [mailto:rt@krbdev.mit.edu]
Sent: Thursday, December 27, 2012 4:16 PM
To: basch@alum.mit.edu
Subject: [krbdev.mit.edu #7522] AutoReply: krb5-1.11, patch 1 of 4


Greetings,

This message has been automatically generated in response to the
creation of a trouble ticket regarding:
"krb5-1.11, patch 1 of 4",
a summary of which appears below.

There is no need to reply to this message right now. Your ticket has been
assigned an ID of [krbdev.mit.edu #7522].

Please include the string:

[krbdev.mit.edu #7522]

in the subject line of all future correspondence about this issue. To do so,

you may reply to this message.

Thank you,


-------------------------------------------------------------------------
I will be submitting 4 patches:

1) If a Kerberos policy is changed, the iprop ulog needs to be reset
otherwise inconsistencies may result. Basically, a full resync is needed by
the slaves to reacquire the new policies. Otherwise incremental updates may
fail because the updated policy information will not be correctly
associated.

2) Kproplog should treat the ulog as a circular buffer. Patch #3
affects kproplog's behavior. Therefore, if the ulog is not fully populated,
the references to the circular buffer should be computed based on the
indices.

3) Allow slaves to capture ulog updates. This facilitates promoting a
slave as a master without having to have all other slaves do a full resync.

4) Add an option to allow tree-based propagation of updates (it
requires 1-3). Specifically, add an option to kpropd to redirect where to
get its updates from and add an option to kadmind to allow it to service
iprop requests only (without enabling all other update functions).



Attached is patch #1 to force a full resync upon policy changes.



Only in src.01/include: kadm5

diff -ru src.00/include/kdb_log.h src.01/include/kdb_log.h

--- src.00/include/kdb_log.h 2012-12-17 21:47:04.000000000 -0500

+++ src.01/include/kdb_log.h 2012-12-21 19:29:13.679830223 -0500

@@ -71,6 +71,7 @@

const char *logname, uint32_t entries,

int caller,

char **db_args);

+extern krb5_error_code ulog_init_header(krb5_context context, uint32_t
recsize);

extern krb5_error_code ulog_add_update(krb5_context context,

kdb_incr_update_t *upd);

extern krb5_error_code ulog_delete_update(krb5_context context,

Only in src.01/lib/kdb: #kdb5.c#

diff -ru src.00/lib/kdb/kdb5.c src.01/lib/kdb/kdb5.c

--- src.00/lib/kdb/kdb5.c 2012-12-17 21:47:05.000000000 -0500

+++ src.01/lib/kdb/kdb5.c 2012-12-21 19:27:53.319790148 -0500

@@ -2319,15 +2319,29 @@

krb5_error_code

krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)

{

+ kdb_log_context *log_ctx = kcontext->kdblog_context;

krb5_error_code status = 0;

kdb_vftabl *v;

status = get_vftabl(kcontext, &v);

if (status)

return status;

+ status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE);

+ if (status)

+ return status;

if (v->create_policy == NULL)

return KRB5_PLUGIN_OP_NOTSUPP;

- return v->create_policy(kcontext, policy);

+ status = v->create_policy(kcontext, policy);

+

+ /* iprop does not support policy mods; force full-resync (re-init ulog)
*/

+ if (!status && log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ }

+

+ ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK);

+ return status;

}

krb5_error_code

@@ -2347,15 +2361,58 @@

krb5_error_code

krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)

{

+ kdb_log_context *log_ctx = kcontext->kdblog_context;

krb5_error_code status = 0;

kdb_vftabl *v;

+ osa_policy_ent_t old_policy = NULL;

status = get_vftabl(kcontext, &v);

if (status)

return status;

if (v->put_policy == NULL)

return KRB5_PLUGIN_OP_NOTSUPP;

- return v->put_policy(kcontext, policy);

+ status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE);

+ if (status)

+ return status;

+ if (log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ if (v->get_policy)

+ v->get_policy(kcontext, policy->name, &old_policy);

+ }

+ status = v->put_policy(kcontext, policy);

+

+ /*

+ * iprop does not support policy mods; force full-resync (re-init
ulog).

+ * However, for policy changes, we need to first check if there were

+ * any *substantive* changes to avoid unnecessary resyncs.

+ */

+

+ if (!status && log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ if (old_policy == NULL ||

+ old_policy->version != policy->version ||

+ old_policy->pw_min_life != policy->pw_min_life ||

+ old_policy->pw_max_life != policy->pw_max_life ||

+ old_policy->pw_min_length != policy->pw_min_length ||

+ old_policy->pw_min_classes != policy->pw_min_classes ||

+ old_policy->pw_history_num != policy->pw_history_num) {

+

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ } else if (policy->version > 1 &&

+ (old_policy->pw_max_fail != policy->pw_max_fail ||

+ old_policy->pw_failcnt_interval !=
policy->pw_failcnt_interval ||

+ old_policy->pw_lockout_duration !=
policy->pw_lockout_duration)) {

+

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ }

+ if (old_policy)

+ krb5_db_free_policy(kcontext, old_policy);

+ }

+

+ ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK);

+ return status;

}

krb5_error_code

@@ -2376,6 +2433,7 @@

krb5_error_code

krb5_db_delete_policy(krb5_context kcontext, char *policy)

{

+ kdb_log_context *log_ctx = kcontext->kdblog_context;

krb5_error_code status = 0;

kdb_vftabl *v;

@@ -2384,7 +2442,20 @@

return status;

if (v->delete_policy == NULL)

return KRB5_PLUGIN_OP_NOTSUPP;

- return v->delete_policy(kcontext, policy);

+ status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE);

+ if (status)

+ return status;

+ status = v->delete_policy(kcontext, policy);

+

+ /* iprop does not support policy mods; force full-resync (re-init ulog)
*/

+ if (!status && log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ }

+

+ ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK);

+ return status;

}

void

Only in src.01/lib/kdb: kdb5.c.~1~

diff -ru src.00/lib/kdb/kdb_log.c src.01/lib/kdb/kdb_log.c

--- src.00/lib/kdb/kdb_log.c 2012-12-17 21:47:05.000000000 -0500

+++ src.01/lib/kdb/kdb_log.c 2012-12-21 19:58:17.450702557 -0500

@@ -121,8 +121,12 @@

new_size = sizeof (kdb_hlog_t);

- new_block = (recsize / ULOG_BLOCK) + 1;

- new_block *= ULOG_BLOCK;

+ if (recsize > ULOG_BLOCK) {

+ new_block = (recsize + ULOG_BLOCK - 1) / ULOG_BLOCK;

+ new_block *= ULOG_BLOCK;

+ }

+ else

+ new_block = ULOG_BLOCK;

new_size += ulogentries * new_block;

@@ -547,6 +551,35 @@

}

/*

+ * Re-init the log header.

+ */

+krb5_error_code

+ulog_init_header(krb5_context context, uint32_t recsize)

+{

+ kdb_log_context *log_ctx;

+ kdb_hlog_t *ulog = NULL;

+ krb5_error_code retval;

+ uint_t block_min;

+

+

+ INIT_ULOG(context);

+

+ /* The caller should already have a lock, but ensure it is exclusive.
*/

+ if ((retval = ulog_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))

+ return retval;

+ ulog_reset(ulog);

+

+ block_min = ULOG_BLOCK; /* Should this be min(ULOG_BLOCK, pagesize)?
*/

+ if (recsize > block_min)

+ ulog->kdb_block = ((recsize + block_min - 1) & (~(block_min-1)));

+

+ ulog_sync_header(ulog);

+

+ /* The caller is responsible for unlocking... */

+ return (0);

+}

+

+/*

* Map the log file to memory for performance and simplicity.

*

* Called by: if iprop_enabled then ulog_map();

Only in src.01/plugins/authdata/greet: Makefile

Only in src.01/plugins/authdata/greet_client: Makefile

Only in src.01/plugins/authdata/greet_server: Makefile

Only in src.01/plugins/kdb/hdb: Makefile

Only in src.01/plugins/locate/python: Makefile

Only in src.01/plugins/preauth/cksum_body: Makefile

Only in src.01/plugins/preauth/securid_sam2: Makefile

Only in src.01/plugins/preauth/wpse: Makefile

Only in src.01/tests/threads: Makefile

Only in src.01/util/collected-client-lib: Makefile


Date: Wed, 02 Jan 2013 17:50:03 -0500
From: Richard Basch <basch@alum.mit.edu>
Subject: RE: [krbdev.mit.edu #7522] AutoReply: krb5-1.11, patch 1 of 4
To: rt@krbdev.mit.edu
RT-Send-Cc:
Download (untitled) / with headers
text/plain 9.6KiB
Iprop currently can cause corruption/discrepancies between the master and
slaves when policy changes occur.

If you change a policy, the policy changes are not reflected to the slaves
and if a slave has to be promoted to a master, there is a problem with the
data. Or even worse, if a policy is created and a user is assigned to that
policy, then as it propagates to the slave, it has issues with the user
entry.

So, patch 1 is "required" for 1.11 for data consistency (it also applies to
prior versions, e.g. since iprop was introduced). This particular patch is
easy to graft into current & prior Kerberos releases.

Patch 1 should be treated on its own merit (I consider the corruption of
data quality between the master and slaves a "serious" bug). Patches 2-4
are more targeted (and progressively move toward "enhancement", and I am
sure patch 4 cannot be introduced until the "next version").


Show quoted text
-----Original Message-----
From: krb5 [mailto:rt@krbdev.mit.edu]
Sent: Thursday, December 27, 2012 4:16 PM
To: basch@alum.mit.edu
Subject: [krbdev.mit.edu #7522] AutoReply: krb5-1.11, patch 1 of 4


Greetings,

This message has been automatically generated in response to the
creation of a trouble ticket regarding:
"krb5-1.11, patch 1 of 4",
a summary of which appears below.

There is no need to reply to this message right now. Your ticket has been
assigned an ID of [krbdev.mit.edu #7522].

Please include the string:

[krbdev.mit.edu #7522]

in the subject line of all future correspondence about this issue. To do so,

you may reply to this message.

Thank you,


-------------------------------------------------------------------------
I will be submitting 4 patches:

1) If a Kerberos policy is changed, the iprop ulog needs to be reset
otherwise inconsistencies may result. Basically, a full resync is needed by
the slaves to reacquire the new policies. Otherwise incremental updates may
fail because the updated policy information will not be correctly
associated.

2) Kproplog should treat the ulog as a circular buffer. Patch #3
affects kproplog's behavior. Therefore, if the ulog is not fully populated,
the references to the circular buffer should be computed based on the
indices.

3) Allow slaves to capture ulog updates. This facilitates promoting a
slave as a master without having to have all other slaves do a full resync.

4) Add an option to allow tree-based propagation of updates (it
requires 1-3). Specifically, add an option to kpropd to redirect where to
get its updates from and add an option to kadmind to allow it to service
iprop requests only (without enabling all other update functions).



Attached is patch #1 to force a full resync upon policy changes.



Only in src.01/include: kadm5

diff -ru src.00/include/kdb_log.h src.01/include/kdb_log.h

--- src.00/include/kdb_log.h 2012-12-17 21:47:04.000000000 -0500

+++ src.01/include/kdb_log.h 2012-12-21 19:29:13.679830223 -0500

@@ -71,6 +71,7 @@

const char *logname, uint32_t entries,

int caller,

char **db_args);

+extern krb5_error_code ulog_init_header(krb5_context context, uint32_t
recsize);

extern krb5_error_code ulog_add_update(krb5_context context,

kdb_incr_update_t *upd);

extern krb5_error_code ulog_delete_update(krb5_context context,

Only in src.01/lib/kdb: #kdb5.c#

diff -ru src.00/lib/kdb/kdb5.c src.01/lib/kdb/kdb5.c

--- src.00/lib/kdb/kdb5.c 2012-12-17 21:47:05.000000000 -0500

+++ src.01/lib/kdb/kdb5.c 2012-12-21 19:27:53.319790148 -0500

@@ -2319,15 +2319,29 @@

krb5_error_code

krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy)

{

+ kdb_log_context *log_ctx = kcontext->kdblog_context;

krb5_error_code status = 0;

kdb_vftabl *v;

status = get_vftabl(kcontext, &v);

if (status)

return status;

+ status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE);

+ if (status)

+ return status;

if (v->create_policy == NULL)

return KRB5_PLUGIN_OP_NOTSUPP;

- return v->create_policy(kcontext, policy);

+ status = v->create_policy(kcontext, policy);

+

+ /* iprop does not support policy mods; force full-resync (re-init ulog)
*/

+ if (!status && log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ }

+

+ ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK);

+ return status;

}

krb5_error_code

@@ -2347,15 +2361,58 @@

krb5_error_code

krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy)

{

+ kdb_log_context *log_ctx = kcontext->kdblog_context;

krb5_error_code status = 0;

kdb_vftabl *v;

+ osa_policy_ent_t old_policy = NULL;

status = get_vftabl(kcontext, &v);

if (status)

return status;

if (v->put_policy == NULL)

return KRB5_PLUGIN_OP_NOTSUPP;

- return v->put_policy(kcontext, policy);

+ status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE);

+ if (status)

+ return status;

+ if (log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ if (v->get_policy)

+ v->get_policy(kcontext, policy->name, &old_policy);

+ }

+ status = v->put_policy(kcontext, policy);

+

+ /*

+ * iprop does not support policy mods; force full-resync (re-init
ulog).

+ * However, for policy changes, we need to first check if there were

+ * any *substantive* changes to avoid unnecessary resyncs.

+ */

+

+ if (!status && log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ if (old_policy == NULL ||

+ old_policy->version != policy->version ||

+ old_policy->pw_min_life != policy->pw_min_life ||

+ old_policy->pw_max_life != policy->pw_max_life ||

+ old_policy->pw_min_length != policy->pw_min_length ||

+ old_policy->pw_min_classes != policy->pw_min_classes ||

+ old_policy->pw_history_num != policy->pw_history_num) {

+

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ } else if (policy->version > 1 &&

+ (old_policy->pw_max_fail != policy->pw_max_fail ||

+ old_policy->pw_failcnt_interval !=
policy->pw_failcnt_interval ||

+ old_policy->pw_lockout_duration !=
policy->pw_lockout_duration)) {

+

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ }

+ if (old_policy)

+ krb5_db_free_policy(kcontext, old_policy);

+ }

+

+ ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK);

+ return status;

}

krb5_error_code

@@ -2376,6 +2433,7 @@

krb5_error_code

krb5_db_delete_policy(krb5_context kcontext, char *policy)

{

+ kdb_log_context *log_ctx = kcontext->kdblog_context;

krb5_error_code status = 0;

kdb_vftabl *v;

@@ -2384,7 +2442,20 @@

return status;

if (v->delete_policy == NULL)

return KRB5_PLUGIN_OP_NOTSUPP;

- return v->delete_policy(kcontext, policy);

+ status = ulog_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE);

+ if (status)

+ return status;

+ status = v->delete_policy(kcontext, policy);

+

+ /* iprop does not support policy mods; force full-resync (re-init ulog)
*/

+ if (!status && log_ctx && log_ctx->iproprole == IPROP_MASTER) {

+ kdb_hlog_t *ulog = NULL;

+ if ((ulog = log_ctx->ulog))

+ (void) ulog_init_header(kcontext, 0);

+ }

+

+ ulog_lock(kcontext, KRB5_LOCKMODE_UNLOCK);

+ return status;

}

void

Only in src.01/lib/kdb: kdb5.c.~1~

diff -ru src.00/lib/kdb/kdb_log.c src.01/lib/kdb/kdb_log.c

--- src.00/lib/kdb/kdb_log.c 2012-12-17 21:47:05.000000000 -0500

+++ src.01/lib/kdb/kdb_log.c 2012-12-21 19:58:17.450702557 -0500

@@ -121,8 +121,12 @@

new_size = sizeof (kdb_hlog_t);

- new_block = (recsize / ULOG_BLOCK) + 1;

- new_block *= ULOG_BLOCK;

+ if (recsize > ULOG_BLOCK) {

+ new_block = (recsize + ULOG_BLOCK - 1) / ULOG_BLOCK;

+ new_block *= ULOG_BLOCK;

+ }

+ else

+ new_block = ULOG_BLOCK;

new_size += ulogentries * new_block;

@@ -547,6 +551,35 @@

}

/*

+ * Re-init the log header.

+ */

+krb5_error_code

+ulog_init_header(krb5_context context, uint32_t recsize)

+{

+ kdb_log_context *log_ctx;

+ kdb_hlog_t *ulog = NULL;

+ krb5_error_code retval;

+ uint_t block_min;

+

+

+ INIT_ULOG(context);

+

+ /* The caller should already have a lock, but ensure it is exclusive.
*/

+ if ((retval = ulog_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))

+ return retval;

+ ulog_reset(ulog);

+

+ block_min = ULOG_BLOCK; /* Should this be min(ULOG_BLOCK, pagesize)?
*/

+ if (recsize > block_min)

+ ulog->kdb_block = ((recsize + block_min - 1) & (~(block_min-1)));

+

+ ulog_sync_header(ulog);

+

+ /* The caller is responsible for unlocking... */

+ return (0);

+}

+

+/*

* Map the log file to memory for performance and simplicity.

*

* Called by: if iprop_enabled then ulog_map();

Only in src.01/plugins/authdata/greet: Makefile

Only in src.01/plugins/authdata/greet_client: Makefile

Only in src.01/plugins/authdata/greet_server: Makefile

Only in src.01/plugins/kdb/hdb: Makefile

Only in src.01/plugins/locate/python: Makefile

Only in src.01/plugins/preauth/cksum_body: Makefile

Only in src.01/plugins/preauth/securid_sam2: Makefile

Only in src.01/plugins/preauth/wpse: Makefile

Only in src.01/tests/threads: Makefile

Only in src.01/util/collected-client-lib: Makefile


Download (untitled) / with headers
text/plain 1.1KiB
All four patches were mangled by your email client. If you send them as
text/plain attachments rather than pasting them inline, they might come
through better. Alternatively, we actually prefer getting code
contributions as github pull requests these days, but that's not
mandatory.

For this patch:

* What is the purpose of the ulog_resize() change?

* What is the purpose of the recsize parameter to ulog_init_header()?

* In krb5_db_put_policy(), if we need code to check whether the policy
has changed, it should be factored out into a predicate function, which
should handle policy tl-data. But I'd much rather eliminate the need to
check.

I believe non-substantive policy changes happen frequently because of
the policy refcount. Nico and I have discussed getting rid of the
refcount, and dealing with the problem of dangling policy references at
delete time (or just letting dangling policy references be equivalent to
no policy). It is already easy for policy refcounts to get out of sync
between master and slaves for a variety of reasons, which is a problem
when a slave is promoted to the master.
Download (untitled) / with headers
text/plain 1.9KiB
Resetting the ulog header to the zero state is not an adequate way to
force a full dump as things currently stand, for several reasons:

1. Let's say a slave's serial number is N, and then a policy operation
happens on the master. If N additional principal operations occur on
the master before the slave asks for incrementals, the slave and master
will have the same serial number and the slave will appear up to date.
(Variations on this problem occur if slightly more than N updates occur
on the master before the slave asks.)

2. Conversely, if the slave takes an update immediately (while the
master's sno is still 0), the slave will transmit an sno if 0 when it
next asks for incrementals. The master will interpret this as a slave
with a fresh database, and will say a full dump is needed again. So a
slave could continually take full dumps over and over again after a
single policy change.

3. Assume we fix #2 somehow. Now, say a policy change happens, then a
slave takes a full dump, then another policy change happens. How do we
know that the slave should take another full dump?

It turns out that the iprop protocol and on-disk metadata include
timestamps as well as serial numbers. These can be used to detect
reused serial numbers and address the above problems. But (1) we would
need to fix iprop_get_updates_1_svc and ulog_get_entries to actually use
the timestamps instead of just ignoring them, and (2) when we
reinitialize the ulog, we need to set the timestamps to the current
time. There are also potential issues with multiple changes occurring
within the granularity of gettimeofday(), although those may be minor.
More fully implementing timestamps also has the benefit of handling some
wrapped-sno scenarios.

Alternatively, we could force a full dump by just setting kdb_first_sno
equal to kdb_last_sno + 1. I'm not sure if there would be problems with
the details there (like what do we set kdb_first_time to?).

(Side note: kproplog -R has the same problem as this proposed patch.)
I misread the existing code a bit; the situation with timestamps isn't
quite as bad as I thought. We do check them, but only for actual iprop
entries; we don't check against the timestamps in the ulog header.
From: ghudson@mit.edu
Subject: SVN Commit

Propagate policy changes over iprop via full dump

Since iprop cannot carry policy changes, force a full resync to happen
each time a policy change occurs. Based on a patch from
Richard Basch <basch@alum.mit.edu>.

https://github.com/krb5/krb5/commit/720e0f5bcf481db3b6e43652cb6577c012b5337e
Author: Greg Hudson <ghudson@mit.edu>
Commit: 720e0f5bcf481db3b6e43652cb6577c012b5337e
Branch: master
src/lib/kdb/kdb5.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--
src/tests/t_iprop.py | 30 +++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 3 deletions(-)