svn rev #23038: trunk/src/ include/ kadmin/cli/ kadmin/dbutil/ kadmin/server/ ...

ghudson@MIT.EDU ghudson at MIT.EDU
Sun Oct 25 12:55:13 EDT 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=23038
Commit By: ghudson
Log Message:
ticket: 6577
subject: Account lockout

Merge Luke's users/lhoward/lockout2 branch to trunk.  Implements
account lockout policies for preauth-using principals using existing
principal metadata fields and new policy fields.  The kadmin API
version is bumped from 2 to 3 to compatibly extend the policy_ent_rec
structure.



Changed Files:
U   trunk/src/include/iprop.h
U   trunk/src/include/iprop_hdr.h
U   trunk/src/include/kdb.h
U   trunk/src/kadmin/cli/kadmin.c
U   trunk/src/kadmin/dbutil/dump.c
U   trunk/src/kadmin/dbutil/kadm5_create.c
U   trunk/src/kadmin/dbutil/kdb5_util.M
U   trunk/src/kadmin/dbutil/kdb5_util.c
U   trunk/src/kadmin/server/ipropd_svc.c
U   trunk/src/kadmin/server/ovsec_kadmd.c
U   trunk/src/kadmin/server/server_stubs.c
U   trunk/src/kadmin/testing/scripts/init_db
U   trunk/src/kadmin/testing/scripts/start_servers_local
U   trunk/src/kadmin/testing/tcl/util.t
U   trunk/src/kadmin/testing/util/tcl_kadm5.c
U   trunk/src/kdc/do_as_req.c
U   trunk/src/kdc/extern.c
U   trunk/src/kdc/main.c
U   trunk/src/lib/kadm5/admin.h
U   trunk/src/lib/kadm5/admin_internal.h
U   trunk/src/lib/kadm5/clnt/client_init.c
U   trunk/src/lib/kadm5/kadm_rpc_xdr.c
U   trunk/src/lib/kadm5/server_internal.h
U   trunk/src/lib/kadm5/srv/server_init.c
U   trunk/src/lib/kadm5/srv/server_kdb.c
U   trunk/src/lib/kadm5/srv/svr_policy.c
U   trunk/src/lib/kadm5/srv/svr_principal.c
U   trunk/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp
A   trunk/src/lib/kadm5/unit-test/api.3/
U   trunk/src/lib/kadm5/unit-test/config/unix.exp
U   trunk/src/lib/kadm5/unit-test/destroy-test.c
U   trunk/src/lib/kadm5/unit-test/handle-test.c
U   trunk/src/lib/kadm5/unit-test/init-test.c
U   trunk/src/lib/kadm5/unit-test/iter-test.c
U   trunk/src/lib/kadm5/unit-test/lib/lib.t
U   trunk/src/lib/kadm5/unit-test/randkey-test.c
U   trunk/src/lib/kadm5/unit-test/setkey-test.c
U   trunk/src/lib/kdb/iprop.x
U   trunk/src/lib/kdb/kdb_convert.c
U   trunk/src/plugins/kdb/db2/Makefile.in
U   trunk/src/plugins/kdb/db2/db2_exp.c
U   trunk/src/plugins/kdb/db2/kdb_db2.c
U   trunk/src/plugins/kdb/db2/kdb_db2.h
A   trunk/src/plugins/kdb/db2/kdb_ext.c
A   trunk/src/plugins/kdb/db2/lockout.c
U   trunk/src/plugins/kdb/db2/pol_xdr.c
U   trunk/src/plugins/kdb/db2/policy_db.h
U   trunk/src/plugins/kdb/ldap/ldap_exp.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
A   trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c
U   trunk/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
A   trunk/src/plugins/kdb/ldap/libkdb_ldap/lockout.c
U   trunk/src/slave/kpropd.c
U   trunk/src/slave/kslave_update
Modified: trunk/src/include/iprop.h
===================================================================
--- trunk/src/include/iprop.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/include/iprop.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -205,6 +205,9 @@
 #define IPROP_FULL_RESYNC 2
 extern  kdb_fullresync_result_t * iprop_full_resync_1(void *, CLIENT *);
 extern  kdb_fullresync_result_t * iprop_full_resync_1_svc(void *, struct svc_req *);
+#define IPROP_FULL_RESYNC_EXT 3
+extern	kdb_fullresync_result_t * iprop_full_resync_ext_1(uint32_t *, CLIENT *);
+extern	kdb_fullresync_result_t * iprop_full_resync_ext_1_svc(uint32_t *, struct svc_req *);
 extern int krb5_iprop_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
 
 #else /* K&R C */
@@ -217,6 +220,9 @@
 #define IPROP_FULL_RESYNC 2
 extern  kdb_fullresync_result_t * iprop_full_resync_1();
 extern  kdb_fullresync_result_t * iprop_full_resync_1_svc();
+#define IPROP_FULL_RESYNC_EXT 3
+extern  kdb_fullresync_result_t * iprop_full_resync_ext_1(uint32_t *, CLIENT *);
+extern  kdb_fullresync_result_t * iprop_full_resync_ext_1_svc(uint32_t *, struct svc_req *);
 extern int krb5_iprop_prog_1_freeresult ();
 #endif /* K&R C */
 

Modified: trunk/src/include/iprop_hdr.h
===================================================================
--- trunk/src/include/iprop_hdr.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/include/iprop_hdr.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -35,6 +35,13 @@
 };
 typedef enum iprop_role iprop_role;
 
+/*
+ * Full resync dump versioning
+ */
+#define IPROPX_VERSION_0    0
+#define IPROPX_VERSION_1    1
+#define IPROPX_VERSION      IPROPX_VERSION_1
+
 #ifdef	__cplusplus
 }
 #endif

Modified: trunk/src/include/kdb.h
===================================================================
--- trunk/src/include/kdb.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/include/kdb.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -169,6 +169,10 @@
     krb5_ui_4       pw_min_classes;
     krb5_ui_4       pw_history_num;
     krb5_ui_4       policy_refcnt;
+    /* Only valid if version > 1 */
+    krb5_ui_4       pw_max_fail;                /* pwdMaxFailure */
+    krb5_ui_4       pw_failcnt_interval;        /* pwdFailureCountInterval */
+    krb5_ui_4       pw_lockout_duration;        /* pwdLockoutDuration */
 } osa_policy_ent_rec, *osa_policy_ent_t;
 
 typedef       void    (*osa_adb_iter_policy_func) (void *, osa_policy_ent_t);
@@ -180,7 +184,7 @@
 
 #define	KRB5_KDB_MAGIC_NUMBER		0xdbdbdbdb
 #define KRB5_KDB_V1_BASE_LENGTH		38
-  
+
 #define KRB5_TL_LAST_PWD_CHANGE		0x0001
 #define KRB5_TL_MOD_PRINC		0x0002
 #define KRB5_TL_KADM_DATA		0x0003
@@ -479,11 +483,6 @@
 				krb5_timestamp        mod_date,
 				krb5_const_principal  mod_princ);
 
-krb5_error_code
-krb5_dbe_update_last_pwd_change( krb5_context          context,
-				 krb5_db_entry       * entry,
-				 krb5_timestamp	  stamp);
-
 void *krb5_db_alloc( krb5_context kcontext,
 		     void *ptr,
 		     size_t size );
@@ -913,6 +912,7 @@
 		   const krb5_data *req,
 		   krb5_data *rep );
 } kdb_vftabl;
+
 #endif /* !defined(_WIN32) */
 
 #endif /* KRB5_KDB5__ */

Modified: trunk/src/kadmin/cli/kadmin.c
===================================================================
--- trunk/src/kadmin/cli/kadmin.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/cli/kadmin.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -486,7 +486,7 @@
                princstr);
         retval = kadm5_init_with_creds(context, princstr, cc, svcname, &params,
                                        KADM5_STRUCT_VERSION,
-                                       KADM5_API_VERSION_2, db_args, &handle);
+                                       KADM5_API_VERSION_3, db_args, &handle);
     } else if (use_keytab) {
         if (keytab_name)
             printf("Authenticating as principal %s with keytab %s.\n",
@@ -496,13 +496,13 @@
                    princstr);
         retval = kadm5_init_with_skey(context, princstr, keytab_name, svcname,
                                       &params, KADM5_STRUCT_VERSION,
-                                      KADM5_API_VERSION_2, db_args, &handle);
+                                      KADM5_API_VERSION_3, db_args, &handle);
     } else {
         printf("Authenticating as principal %s with password.\n",
                princstr);
         retval = kadm5_init_with_password(context, princstr, password, svcname,
                                           &params, KADM5_STRUCT_VERSION,
-                                          KADM5_API_VERSION_2, db_args,
+                                          KADM5_API_VERSION_3, db_args,
                                           &handle);
     }
     if (retval) {
@@ -970,6 +970,11 @@
             }
         }
 #endif /* APPLE_PKINIT */
+        if (strlen(argv[i]) == 7 && !strcmp("-unlock", argv[i])) {
+            oprinc->fail_auth_count = 0;
+            *mask |= KADM5_FAIL_AUTH_COUNT;
+            continue;
+        }
         if (!strcmp("-e", argv[i])) {
             if (++i > argc - 2)
                 return -1;
@@ -1047,7 +1052,7 @@
 {
     fprintf(stderr, "usage: modify_principal [options] principal\n");
     fprintf(stderr, "\toptions are:\n");
-    fprintf(stderr, "\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] [{+|-}attribute]\n");
+    fprintf(stderr, "\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n");
     fprintf(stderr, "\tattributes are:\n");
     fprintf(stderr, "%s%s%s",
             "\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n",
@@ -1496,6 +1501,33 @@
                 *mask |= KADM5_PW_HISTORY_NUM;
                 continue;
             }
+        } else if (strlen(argv[i]) == 11 &&
+                   !strcmp(argv[i], "-maxfailure")) {
+            if (++i > argc - 2)
+                return -1;
+            else {
+                policy->pw_max_fail = atoi(argv[i]);
+                *mask |= KADM5_PW_MAX_FAILURE;
+                continue;
+            }
+        } else if (strlen(argv[i]) == 21 &&
+                   !strcmp(argv[i], "-failurecountinterval")) {
+            if (++i > argc - 2)
+                return -1;
+            else {
+                policy->pw_failcnt_interval = atoi(argv[i]);
+                *mask |= KADM5_PW_FAILURE_COUNT_INTERVAL;
+                continue;
+            }
+        } else if (strlen(argv[i]) == 16 &&
+                   !strcmp(argv[i], "-lockoutduration")) {
+            if (++i > argc - 2)
+                return -1;
+            else {
+                policy->pw_lockout_duration = atoi(argv[i]);
+                *mask |= KADM5_PW_LOCKOUT_DURATION;
+                continue;
+            }
         } else
             return -1;
     }
@@ -1511,7 +1543,8 @@
 {
     fprintf(stderr, "usage; %s [options] policy\n", func);
     fprintf(stderr, "\toptions are:\n");
-    fprintf(stderr, "\t\t[-maxlife time] [-minlife time] [-minlength length]\n\t\t[-minclasses number] [-history number]\n");
+    fprintf(stderr, "\t\t[-maxlife time] [-minlife time] [-minlength length]\n\t\t[-minclasses number] [-history number]\n\t\t[-maxfailure number] [-failurecountinterval time]\n");
+    fprintf(stderr, "\t\t[-lockoutduration time]\n");
 }
 
 void
@@ -1607,11 +1640,19 @@
                policy.pw_min_classes);
         printf("Number of old keys kept: %ld\n", policy.pw_history_num);
         printf("Reference count: %ld\n", policy.policy_refcnt);
+        printf("Maximum password failures before lockout: %ld\n",
+                policy.pw_max_fail);
+        printf("Password failure count reset interval: %ld\n",
+                (long)policy.pw_failcnt_interval);
+        printf("Password lockout duration: %ld\n",
+                (long)policy.pw_lockout_duration);
     } else {
-        printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\n",
+        printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\n",
                policy.policy, policy.pw_max_life, policy.pw_min_life,
                policy.pw_min_length, policy.pw_min_classes,
-               policy.pw_history_num, policy.policy_refcnt);
+               policy.pw_history_num, policy.policy_refcnt,
+               policy.pw_max_fail, (long)policy.pw_failcnt_interval,
+               (long)policy.pw_lockout_duration);
     }
     kadm5_free_policy_ent(handle, &policy);
 }

Modified: trunk/src/kadmin/dbutil/dump.c
===================================================================
--- trunk/src/kadmin/dbutil/dump.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/dbutil/dump.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -66,13 +66,17 @@
 #include <regexp.h>
 #endif	/* !HAVE_REGCOMP && HAVE_REGEXP_H */
 
+#define FLAG_VERBOSE	0x1	/* be verbose */
+#define FLAG_UPDATE	0x2	/* processing an update */
+#define FLAG_OMIT_NRA	0x4	/* avoid dumping non-replicated attrs */
+
 struct dump_args {
     char		*programname;
     FILE		*ofile;
     krb5_context	kcontext;
     char		**names;
     int			nnames;
-    int			verbose;
+    int			flags;
 };
 
 static krb5_error_code dump_k5beta_iterator (krb5_pointer,
@@ -92,6 +96,7 @@
 static krb5_error_code dump_ov_princ (krb5_pointer,
 				      krb5_db_entry *);
 static void dump_k5beta7_policy (void *, osa_policy_ent_t);
+static void dump_r1_8_policy (void *, osa_policy_ent_t);
 
 typedef krb5_error_code (*dump_func)(krb5_pointer,
 				     krb5_db_entry *);
@@ -102,6 +107,8 @@
 				   FILE *, int, int *);
 static int process_k5beta7_record (char *, krb5_context,
 				   FILE *, int, int *);
+static int process_r1_8_record (char *, krb5_context,
+				   FILE *, int, int *);
 static int process_ov_record (char *, krb5_context,
 			      FILE *, int, int *);
 typedef krb5_error_code (*load_func)(char *, krb5_context,
@@ -172,6 +179,24 @@
      dump_k5beta7_policy,
      process_k5beta7_record,
 };
+dump_version r1_8_version = {
+     "Kerberos version 5 release 1.8",
+     "kdb5_util load_dump version 6\n",
+     0,
+     0,
+     dump_k5beta7_princ_withpolicy,
+     dump_r1_8_policy,
+     process_r1_8_record,
+};
+dump_version ipropx_1_version = {
+     "Kerberos iprop extensible version",
+     "ipropx",
+     0,
+     0,
+     dump_k5beta7_princ_withpolicy,
+     dump_r1_8_policy,
+     process_r1_8_record,
+};
 
 /* External data */
 extern char		*current_dbname;
@@ -197,6 +222,7 @@
 #define stand_fmt_name		"Kerberos version 5"
 #define old_fmt_name		"Kerberos version 5 old format"
 #define b6_fmt_name		"Kerberos version 5 beta 6 format"
+#define r1_3_fmt_name		"Kerberos version 5 release 1.3 format"
 #define ofopen_error		"%s: cannot open %s for writing (%s)\n"
 #define oflock_error		"%s: cannot lock %s (%s)\n"
 #define dumprec_err		"%s: error performing %s dump (%s)\n"
@@ -257,6 +283,7 @@
 static const char updateoption[] = "-update";
 static const char hashoption[] = "-hash";
 static const char ovoption[] = "-ov";
+static const char r13option[] = "-r13";
 static const char dump_tmptrail[] = "~";
 
 /*
@@ -646,8 +673,11 @@
 		(krb5_int32) pkey->key_data_kvno,
 		entry->max_life, entry->max_renewable_life,
 		1 /* Fake mkvno */, entry->expiration, entry->pw_expiration,
-		last_pwd_change, entry->last_success, entry->last_failed,
-		entry->fail_auth_count, mod_name, mod_date,
+		last_pwd_change,
+		(arg->flags & FLAG_OMIT_NRA) ? 0 : entry->last_success,
+		(arg->flags & FLAG_OMIT_NRA) ? 0 : entry->last_failed,
+		(arg->flags & FLAG_OMIT_NRA) ? 0 : entry->fail_auth_count,
+		mod_name, mod_date,
 		entry->attributes, pkey->key_data_type[1]);
 
 	/* Pound out the salt data, if present. */
@@ -670,7 +700,7 @@
 	}
 	fprintf(arg->ofile, ";\n");
 	/* If we're blabbing, do it */
-	if (arg->verbose)
+	if (arg->flags & FLAG_VERBOSE)
 	    fprintf(stderr, "%s\n", name);
 	free(mod_name);
     }
@@ -790,9 +820,9 @@
 		    entry->max_renewable_life,
 		    entry->expiration,
 		    entry->pw_expiration,
-		    entry->last_success,
-		    entry->last_failed,
-		    entry->fail_auth_count);
+		    (arg->flags & FLAG_OMIT_NRA) ? 0 : entry->last_success,
+		    (arg->flags & FLAG_OMIT_NRA) ? 0 : entry->last_failed,
+		    (arg->flags & FLAG_OMIT_NRA) ? 0 : entry->fail_auth_count);
 	    /* Pound out tagged data. */
 	    for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) {
 		if (tlp->tl_data_type == KRB5_TL_KADM_DATA && !kadm)
@@ -839,7 +869,7 @@
 	    /* Print trailer */
 	    fprintf(arg->ofile, ";\n");
 
-	    if (arg->verbose)
+	    if (arg->flags & FLAG_VERBOSE)
 		fprintf(stderr, "%s\n", name);
 	}
 	else {
@@ -926,6 +956,19 @@
 	     entry->policy_refcnt);
 }
 
+void dump_r1_8_policy(void *data, osa_policy_ent_t entry)
+{
+     struct dump_args *arg;
+
+     arg = (struct dump_args *) data;
+     fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
+	     entry->name,
+	     entry->pw_min_life, entry->pw_max_life, entry->pw_min_length,
+	     entry->pw_min_classes, entry->pw_history_num,
+	     entry->policy_refcnt, entry->pw_max_fail,
+	     entry->pw_failcnt_interval, entry->pw_lockout_duration);
+}
+
 static void print_key_data(FILE *f, krb5_key_data *key_data)
 {
      int c;
@@ -963,7 +1006,8 @@
 static krb5_error_code dump_ov_princ(krb5_pointer ptr, krb5_db_entry *kdb)
 {
     char *princstr;
-    int	x, y, foundcrc;
+    unsigned int x;
+    int	y, foundcrc;
     struct dump_args *arg;
     krb5_tl_data tl_data;
     osa_princ_ent_rec adb;
@@ -986,7 +1030,7 @@
 	 return 0;
 
     memset(&adb, 0, sizeof(adb));
-    xdrmem_create(&xdrs, tl_data.tl_data_contents,
+    xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents,
 		  tl_data.tl_data_length, XDR_DECODE);
     if (! xdr_osa_princ_ent_rec(&xdrs, &adb)) {
 	 xdr_destroy(&xdrs);
@@ -1034,7 +1078,7 @@
 
 /*
  * usage is:
- *	dump_db [-old] [-b6] [-b7] [-ov] [-verbose] [-mkey_convert]
+ *	dump_db [-old] [-b6] [-b7] [-ov] [-r13] [-verbose] [-mkey_convert]
  *		[-new_mkey_file mkey_file] [-rev] [-recurse]
  *		[filename [principals...]]
  */
@@ -1054,13 +1098,14 @@
     bool_t		dump_sno = FALSE;
     kdb_log_context	*log_ctx;
     char		**db_args = 0; /* XXX */
+    unsigned int	ipropx_version = IPROPX_VERSION_0;
 
     /*
      * Parse the arguments.
      */
     ofile = (char *) NULL;
-    dump = &r1_3_version;
-    arglist.verbose = 0;
+    dump = &r1_8_version;
+    arglist.flags = 0;
     new_mkey_file = 0;
     mkey_convert = 0;
     backwards = 0;
@@ -1079,9 +1124,13 @@
 	     dump = &beta7_version;
 	else if (!strcmp(argv[aindex], ovoption))
 	     dump = &ov_version;
-	else if (!strcmp(argv[aindex], ipropoption)) {
+	else if (!strcmp(argv[aindex], r13option))
+	     dump = &r1_3_version;
+	else if (!strncmp(argv[aindex], ipropoption, sizeof(ipropoption) - 1)) {
 	    if (log_ctx && log_ctx->iproprole) {
-		dump = &iprop_version;
+		/* Note: ipropx_version is the maximum version acceptable */
+		ipropx_version = atoi(argv[aindex] + sizeof(ipropoption) - 1);
+		dump = ipropx_version ? &ipropx_1_version : &iprop_version;
 		/*
 		 * dump_sno is used to indicate if the serial
 		 * # should be populated in the output
@@ -1089,13 +1138,18 @@
 		 * the slave's update log when loading
 		 */
 		dump_sno = TRUE;
+		/*
+		 * FLAG_OMIT_NRA is set to indicate that non-replicated
+		 * attributes should be omitted.
+		 */
+		arglist.flags |= FLAG_OMIT_NRA;
 	    } else {
 		fprintf(stderr, _("Iprop not enabled\n"));
 		exit_status++;
 		return;
 	    }
 	} else if (!strcmp(argv[aindex], verboseoption))
-	    arglist.verbose++;
+	    arglist.flags |= FLAG_VERBOSE;
 	else if (!strcmp(argv[aindex], "-mkey_convert"))
 	    mkey_convert = 1;
 	else if (!strcmp(argv[aindex], "-new_mkey_file")) {
@@ -1263,6 +1317,8 @@
 		goto unlock_and_return;
 	    }
 
+	    if (ipropx_version)
+		fprintf(f, " %u", IPROPX_VERSION);
 	    fprintf(f, " %u", log_ctx->ulog->kdb_last_sno);
 	    fprintf(f, " %u", log_ctx->ulog->kdb_last_time.seconds);
 	    fprintf(f, " %u", log_ctx->ulog->kdb_last_time.useconds);
@@ -1467,11 +1523,11 @@
  * Returns -1 for end of file, 0 for success and 1 for failure.
  */
 static int
-process_k5beta_record(fname, kcontext, filep, verbose, linenop)
+process_k5beta_record(fname, kcontext, filep, flags, linenop)
     char		*fname;
     krb5_context	kcontext;
     FILE		*filep;
-    int			verbose;
+    int			flags;
     int			*linenop;
 {
     int			nmatched;
@@ -1723,7 +1779,7 @@
 				error++;
 			    }
 			    else {
-				if (verbose)
+				if (flags & FLAG_VERBOSE)
 				    fprintf(stderr, add_princ_fmt, name);
 				retval = 0;
 			    }
@@ -1773,11 +1829,11 @@
  * Returns -1 for end of file, 0 for success and 1 for failure.
  */
 static int
-process_k5beta6_record(fname, kcontext, filep, verbose, linenop)
+process_k5beta6_record(fname, kcontext, filep, flags, linenop)
     char		*fname;
     krb5_context	kcontext;
     FILE		*filep;
-    int			verbose;
+    int			flags;
     int			*linenop;
 {
     int			retval;
@@ -2024,7 +2080,7 @@
 				name, error_message(kret));
 		    }
 		    else {
-			if (verbose)
+			if (flags & FLAG_VERBOSE)
 			    fprintf(stderr, add_princ_fmt, name);
 			retval = 0;
 		    }
@@ -2061,17 +2117,19 @@
 }
 
 static int 
-process_k5beta7_policy(fname, kcontext, filep, verbose, linenop)
+process_k5beta7_policy(fname, kcontext, filep, flags, linenop)
     char		*fname;
     krb5_context	kcontext;
     FILE		*filep;
-    int			verbose;
+    int			flags;
     int			*linenop;
 {
     osa_policy_ent_rec rec;
     char namebuf[1024];
     int nread, ret;
 
+    memset(&rec, 0, sizeof(rec));
+
     (*linenop)++;
     rec.name = namebuf;
 
@@ -2095,23 +2153,73 @@
 	      return 1;
 	 }
     }
-    if (verbose)
+    if (flags & FLAG_VERBOSE)
 	 fprintf(stderr, "created policy %s\n", rec.name);
     
     return 0;
 }
 
+static int
+process_r1_8_policy(fname, kcontext, filep, flags, linenop)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			flags;
+    int			*linenop;
+{
+    osa_policy_ent_rec rec;
+    char namebuf[1024];
+    int nread, ret;
+
+    memset(&rec, 0, sizeof(rec));
+
+    (*linenop)++;
+    rec.name = namebuf;
+
+    /*
+     * To make this compatible with future policy extensions, we
+     * ignore any additional values.
+     */
+    nread = fscanf(filep, "%1024s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d",
+		   rec.name,
+		   &rec.pw_min_life, &rec.pw_max_life,
+		   &rec.pw_min_length, &rec.pw_min_classes,
+		   &rec.pw_history_num, &rec.policy_refcnt,
+		   &rec.pw_max_fail, &rec.pw_failcnt_interval,
+		   &rec.pw_lockout_duration);
+    if (nread == EOF)
+	 return -1;
+    else if (nread < 10) {
+	 fprintf(stderr, "cannot parse policy on line %d (%d read)\n",
+		 *linenop, nread);
+	 return 1;
+    }
+
+    if ((ret = krb5_db_create_policy(kcontext, &rec))) {
+	 if (ret &&
+	     ((ret = krb5_db_put_policy(kcontext, &rec)))) {
+	      fprintf(stderr, "cannot create policy on line %d: %s\n",
+		      *linenop, error_message(ret));
+	      return 1;
+	 }
+    }
+    if (flags & FLAG_VERBOSE)
+	 fprintf(stderr, "created policy %s\n", rec.name);
+
+    return 0;
+}
+
 /*
  * process_k5beta7_record()	- Handle a dump record in krb5b7 format.
  *
  * Returns -1 for end of file, 0 for success and 1 for failure.
  */
 static int
-process_k5beta7_record(fname, kcontext, filep, verbose, linenop)
+process_k5beta7_record(fname, kcontext, filep, flags, linenop)
     char		*fname;
     krb5_context	kcontext;
     FILE		*filep;
-    int			verbose;
+    int			flags;
     int			*linenop;
 {
      int nread;
@@ -2123,10 +2231,10 @@
      else if (nread != 1)
 	  return 1;
      if (strcmp(rectype, "princ") == 0)
-	  process_k5beta6_record(fname, kcontext, filep, verbose,
+	  process_k5beta6_record(fname, kcontext, filep, flags,
 				 linenop);
      else if (strcmp(rectype, "policy") == 0)
-	  process_k5beta7_policy(fname, kcontext, filep, verbose,
+	  process_k5beta7_policy(fname, kcontext, filep, flags,
 				 linenop);
      else {
 	  fprintf(stderr, "unknown record type \"%s\" on line %d\n",
@@ -2143,11 +2251,11 @@
  * Returns -1 for end of file, 0 for success and 1 for failure.
  */
 static int
-process_ov_record(fname, kcontext, filep, verbose, linenop)
+process_ov_record(fname, kcontext, filep, flags, linenop)
     char		*fname;
     krb5_context	kcontext;
     FILE		*filep;
-    int			verbose;
+    int			flags;
     int			*linenop;
 {
      int nread;
@@ -2159,10 +2267,10 @@
      else if (nread != 1)
 	  return 1;
      if (strcmp(rectype, "princ") == 0)
-	  process_ov_principal(fname, kcontext, filep, verbose,
+	  process_ov_principal(fname, kcontext, filep, flags,
 			       linenop);
      else if (strcmp(rectype, "policy") == 0)
-	  process_k5beta7_policy(fname, kcontext, filep, verbose,
+	  process_k5beta7_policy(fname, kcontext, filep, flags,
 				 linenop);
      else if (strcmp(rectype, "End") == 0)
 	  return -1;
@@ -2176,15 +2284,51 @@
 }
 
 /*
+ * process_r1_8_record()	- Handle a dump record in krb5 1.8 format.
+ *
+ * Returns -1 for end of file, 0 for success and 1 for failure.
+ */
+static int
+process_r1_8_record(fname, kcontext, filep, flags, linenop)
+    char		*fname;
+    krb5_context	kcontext;
+    FILE		*filep;
+    int			flags;
+    int			*linenop;
+{
+     int nread;
+     char rectype[100];
+
+     nread = fscanf(filep, "%100s\t", rectype);
+     if (nread == EOF)
+	  return -1;
+     else if (nread != 1)
+	  return 1;
+     if (strcmp(rectype, "princ") == 0)
+	  process_k5beta6_record(fname, kcontext, filep, flags,
+				 linenop);
+     else if (strcmp(rectype, "policy") == 0)
+	  process_r1_8_policy(fname, kcontext, filep, flags,
+			      linenop);
+     else {
+	  fprintf(stderr, "unknown record type \"%s\" on line %d\n",
+		  rectype, *linenop);
+	  return 1;
+     }
+
+     return 0;
+}
+
+/*
  * restore_dump()	- Restore the database from any version dump file.
  */
 static int
-restore_dump(programname, kcontext, dumpfile, f, verbose, dump)
+restore_dump(programname, kcontext, dumpfile, f, flags, dump)
     char		*programname;
     krb5_context	kcontext;
     char		*dumpfile;
     FILE		*f;
-    int			verbose;
+    int			flags;
     dump_version	*dump;
 {
     int		error;	
@@ -2199,7 +2343,7 @@
     while (!(error = (*dump->load_record)(dumpfile,
 					  kcontext, 
 					  f,
-					  verbose,
+					  flags,
 					  &lineno)))
 	 ;
     if (error != -1)
@@ -2211,8 +2355,8 @@
 }
 
 /*
- * Usage: load_db [-old] [-ov] [-b6] [-b7] [-verbose] [-update] [-hash]
- *		filename
+ * Usage: load_db [-old] [-ov] [-b6] [-b7] [-r13] [-verbose]
+ *                [-update] [-hash] filename
  */
 void
 load_db(argc, argv)
@@ -2230,13 +2374,13 @@
     char		*dbname_tmp;
     char		buf[BUFSIZ];
     dump_version	*load;
-    int			update, verbose;
+    int			flags;
     krb5_int32		crflags;
     int			aindex;
     int			db_locked = 0;
     char		iheader[MAX_HEADER];
     kdb_log_context	*log_ctx;
-    int			add_update = 1;
+    krb5_boolean	add_update = TRUE;
     uint32_t		caller, last_sno, last_seconds, last_useconds;
 
     /*
@@ -2245,8 +2389,7 @@
     dumpfile = (char *) NULL;
     dbname = global_params.dbname;
     load = NULL;
-    update = 0;
-    verbose = 0;
+    flags = 0;
     crflags = KRB5_KDB_CREATE_BTREE;
     exit_status = 0;
     dbname_tmp = (char *) NULL;
@@ -2261,6 +2404,8 @@
 	     load = &beta7_version;
 	else if (!strcmp(argv[aindex], ovoption))
 	     load = &ov_version;
+	else if (!strcmp(argv[aindex], r13option))
+	     load = &r1_3_version;
 	else if (!strcmp(argv[aindex], ipropoption)) {
 	    if (log_ctx && log_ctx->iproprole) {
 		load = &iprop_version;
@@ -2271,9 +2416,9 @@
 		return;
 	    }
 	} else if (!strcmp(argv[aindex], verboseoption))
-	    verbose = 1;
+	    flags |= FLAG_VERBOSE;
 	else if (!strcmp(argv[aindex], updateoption))
-	    update = 1;
+	    flags |= FLAG_UPDATE;
 	else if (!strcmp(argv[aindex], hashoption)) {
 	    if (!add_db_arg("hash=true")) {
 		com_err(progname, ENOMEM, "while parsing command arguments\n");
@@ -2342,6 +2487,7 @@
     fgets(buf, sizeof(buf), f);
     if (load) {
 	 /* only check what we know; some headers only contain a prefix */
+	 /* NB: this should work for ipropx even though load is iprop */
 	 if (strncmp(buf, load->header, strlen(load->header)) != 0) {
 	      fprintf(stderr, head_bad_fmt, progname, dumpfile);
 	      exit_status++;
@@ -2358,6 +2504,8 @@
 	      load = &beta7_version;
 	 else if (strcmp(buf, r1_3_version.header) == 0)
 	      load = &r1_3_version;
+	 else if (strcmp(buf, r1_8_version.header) == 0)
+	      load = &r1_8_version;
 	 else if (strncmp(buf, ov_version.header,
 			  strlen(ov_version.header)) == 0)
 	      load = &ov_version;
@@ -2368,7 +2516,7 @@
 	      return;
 	 }
     }
-    if (load->updateonly && !update) {
+    if (load->updateonly && !(flags & FLAG_UPDATE)) {
 	 fprintf(stderr, "%s: dump version %s can only be loaded with the "
 		 "-update flag\n", progname, load->name);
 	 exit_status++;
@@ -2381,7 +2529,7 @@
      * be the live db.
      */
     newparams = global_params;
-    if (! update) {
+    if (! (flags & FLAG_UPDATE)) {
 	 newparams.mask |= KADM5_CONFIG_DBNAME;
 	 newparams.dbname = dbname_tmp;
 
@@ -2397,12 +2545,17 @@
 	     com_err(progname, ENOMEM, "computing parameters for database");
 	     exit(1);
 	 }
+
+	 if (!add_update && !add_db_arg("merge_nra")) {
+	     com_err(progname, ENOMEM, "computing parameters for database");
+	     exit(1);
+	 }
     }
     
     /*
      * If not an update restoration, create the database. otherwise open
      */
-    if (!update) {
+    if (!(flags & FLAG_UPDATE)) {
 	if((kret = krb5_db_create(kcontext, db5util_db_args))) {
 	    const char *emsg = krb5_get_error_message(kcontext, kret);
 	    /* 
@@ -2452,7 +2605,10 @@
      * If an update restoration, make sure the db is left unusable if
      * the update fails.
      */
-    if ((kret = krb5_db_lock(kcontext, update?KRB5_DB_LOCKMODE_PERMANENT: KRB5_DB_LOCKMODE_EXCLUSIVE))) {
+    if ((kret = krb5_db_lock(kcontext,
+			     (flags & FLAG_UPDATE) ?
+				KRB5_DB_LOCKMODE_PERMANENT :
+				KRB5_DB_LOCKMODE_EXCLUSIVE))) {
 	/* 
 	 * Ignore a not supported error since there is nothing to do about it
 	 * anyway.
@@ -2491,7 +2647,7 @@
 	 * 	we could implicity delete db entries during a replace
 	 *	no advantage in incr updates when entire db is replaced
 	 */
-	if (!update) {
+	if (!(flags & FLAG_UPDATE)) {
 	    memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t));
 
 	    log_ctx->ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC;
@@ -2502,9 +2658,30 @@
 	    log_ctx->iproprole = IPROP_NULL;
 
 	    if (!add_update) {
-		sscanf(buf, "%s %u %u %u", iheader, &last_sno,
+		unsigned int ipropx_version = IPROPX_VERSION_0;
+
+		if (!strncmp(buf, "ipropx ", sizeof("ipropx ") - 1))
+		    sscanf(buf, "%s %u %u %u %u", iheader,
+			   &ipropx_version, &last_sno,
+			   &last_seconds, &last_useconds);
+		else
+		    sscanf(buf, "%s %u %u %u", iheader, &last_sno,
 		       &last_seconds, &last_useconds);
 
+		switch (ipropx_version) {
+		case IPROPX_VERSION_0:
+		    load = &iprop_version;
+		    break;
+		case IPROPX_VERSION_1:
+		    load = &ipropx_1_version;
+		    break;
+		default:
+		    fprintf(stderr, _("%s: Unknown iprop dump version %d\n"),
+			    progname, ipropx_version);
+		    exit_status++;
+		    goto error;
+		}
+
 		log_ctx->ulog->kdb_last_sno = last_sno;
 		log_ctx->ulog->kdb_last_time.seconds =
 		    last_seconds;
@@ -2515,13 +2692,13 @@
     }
 
     if (restore_dump(progname, kcontext, (dumpfile) ? dumpfile : stdin_name,
-		     f, verbose, load)) {
+		     f, flags, load)) {
 	 fprintf(stderr, restfail_fmt,
 		 progname, load->name);
 	 exit_status++;
     }
 
-    if (!update && load->create_kadm5 &&
+    if (!(flags & FLAG_UPDATE) && load->create_kadm5 &&
 	((kret = kadm5_create_magic_princs(&newparams, kcontext)))) {
 	 /* error message printed by create_magic_princs */
 	 exit_status++;
@@ -2544,7 +2721,7 @@
 
     /* close policy db below */
 
-    if (exit_status == 0 && !update) {
+    if (exit_status == 0 && !(flags & FLAG_UPDATE)) {
 	kret = krb5_db_promote(kcontext, db5util_db_args);
 	/* 
 	 * Ignore a not supported error since there is nothing to do about it
@@ -2564,7 +2741,7 @@
      *
      * If an update: if there was no error, unlock the database.
      */
-    if (!update) {
+    if (!(flags & FLAG_UPDATE)) {
 	 if (exit_status) {
 	      kret = krb5_db_destroy(kcontext, db5util_db_args);
 	      /* 

Modified: trunk/src/kadmin/dbutil/kadm5_create.c
===================================================================
--- trunk/src/kadmin/dbutil/kadm5_create.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/dbutil/kadm5_create.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -108,7 +108,7 @@
 	  return retval;
      if ((retval = kadm5_init(context, progname, NULL, NULL, params,
 			      KADM5_STRUCT_VERSION,
-			      KADM5_API_VERSION_2,
+			      KADM5_API_VERSION_3,
 			      db5util_db_args,
 			      &handle))) {
 	  com_err(progname, retval, "while initializing the Kerberos admin interface");

Modified: trunk/src/kadmin/dbutil/kdb5_util.M
===================================================================
--- trunk/src/kadmin/dbutil/kdb5_util.M	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/dbutil/kdb5_util.M	2009-10-25 16:55:12 UTC (rev 23038)
@@ -99,14 +99,14 @@
 .B \-f
 argument can be used to override the keyfile specified at startup.
 .TP
-\fBdump\fP [\fB\-old\fP] [\fB\-b6\fP] [\fB\-b7\fP] [\fB\-ov\fP]
+\fBdump\fP [\fB\-old\fP|\fB-b6\fP|\fB-b7\fP|\fB-ov\fP|\fB-r13\fP]
 [\fB\-verbose\fP] [\fB\-mkey_convert\fP]
 [\fB\-new_mkey_file\fP \fImkey_file\fP] [\fB\-rev\fP] [\fB\-recurse\fP]
 [\fIfilename\fP [\fIprincipals...\fP]]
 .br
 Dumps the current Kerberos and KADM5 database into an ASCII file.  By
 default, the database is dumped in current format, "kdb5_util
-load_dumpversion 5".  If
+load_dump version 6".  If
 .I filename
 is not specified, or is the string "\-", the dump is sent to standard
 output.  Options:
@@ -128,6 +128,9 @@
 .I ovsec_adm_export
 format.
 .TP
+.B \-r13
+causes the dump to be in the Kerberos 5 1.3 format ("kdb5_util load_dump version 5").  This was the dump format produced on releases prior to 1.8.
+.TP
 .B \-verbose
 causes the name of each principal and policy to be printed as it is
 dumped.
@@ -154,7 +157,7 @@
 option will.
 .RE
 .TP
-\fBload\fP [\fB\-old\fP] [\fB\-b6\fP] [\fB\-b7\fP] [\fB\-ov\fP] [\fB\-hash\fP]
+\fBload\fP \fB\-old\fP|\fB-b6\fP|\fB-b7\fP|\fB-ov\fP|\fB-r13\fP] [\fB\-hash\fP]
 [\fB\-verbose\fP] [\fB\-update\fP] \fIfilename dbname\fP
 .br
 Loads a database dump from the named file into the named database.

Modified: trunk/src/kadmin/dbutil/kdb5_util.c
===================================================================
--- trunk/src/kadmin/dbutil/kdb5_util.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/dbutil/kdb5_util.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -90,10 +90,10 @@
 	     "\tcreate	[-s]\n"
 	     "\tdestroy	[-f]\n"
 	     "\tstash	[-f keyfile]\n"
-	     "\tdump	[-old] [-ov] [-b6] [-verbose]\n"
+	     "\tdump	[-old|-ov|-b6|-b7|-r13] [-verbose]\n"
 	     "\t	[-mkey_convert] [-new_mkey_file mkey_file]\n"
 	     "\t	[-rev] [-recurse] [filename [princs...]]\n"
-	     "\tload	[-old] [-ov] [-b6] [-verbose] [-update] filename\n"
+	     "\tload	[-old|-ov|-b6|-b7|-r13] [-verbose] [-update] filename\n"
 	     "\tark	[-e etype_list] principal\n"
 	     "\tadd_mkey [-e etype] [-s]\n"
 	     "\tuse_mkey kvno [time]\n"

Modified: trunk/src/kadmin/server/ipropd_svc.c
===================================================================
--- trunk/src/kadmin/server/ipropd_svc.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/server/ipropd_svc.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -241,8 +241,8 @@
     return (NULL);
 }
 
-kdb_fullresync_result_t *
-iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp)
+static kdb_fullresync_result_t *
+ipropx_resync(uint32_t vers, struct svc_req *rqstp)
 {
     static kdb_fullresync_result_t ret;
     char *tmpf = 0;
@@ -255,6 +255,13 @@
     char *client_name = NULL, *service_name = NULL;
     char *whoami = "iprop_full_resync_1";
 
+    /*
+     * vers contains the highest version number the client is
+     * willing to accept. A client can always accept a lower
+     * version: the version number is indicated in the dump
+     * header.
+     */
+
     /* default return code */
     ret.ret = UPDATE_ERROR;
 
@@ -323,10 +330,12 @@
 
     /*
      * note the -i; modified version of kdb5_util dump format
-     * to include sno (serial number)
+     * to include sno (serial number). This argument is now
+     * versioned (-i0 for legacy dump format, -i1 for ipropx
+     * version 1 format, etc)
      */
-    if (asprintf(&ubuf, "%s dump -i %s </dev/null 2>&1",
-		 KPROPD_DEFAULT_KDB5_UTIL, tmpf) < 0) {
+    if (asprintf(&ubuf, "%s dump -i%d %s </dev/null 2>&1",
+		 KPROPD_DEFAULT_KDB5_UTIL, vers, tmpf) < 0) {
 	krb5_klog_syslog(LOG_ERR,
 			 _("%s: cannot construct kdb5 util dump string too long; out of memory"),
 			 whoami);
@@ -422,6 +431,18 @@
     return (&ret);
 }
 
+kdb_fullresync_result_t *
+iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp)
+{
+    return ipropx_resync(IPROPX_VERSION_0, rqstp);
+}
+
+kdb_fullresync_result_t *
+iprop_full_resync_ext_1_svc(uint32_t *argp, struct svc_req *rqstp)
+{
+    return ipropx_resync(*argp, rqstp);
+}
+
 static int
 check_iprop_rpcsec_auth(struct svc_req *rqstp)
 {
@@ -535,6 +556,12 @@
 	local = (char *(*)()) iprop_full_resync_1_svc;
 	break;
 
+    case IPROP_FULL_RESYNC_EXT:
+	_xdr_argument = xdr_u_int32;
+	_xdr_result = xdr_kdb_fullresync_result_t;
+	local = (char *(*)()) iprop_full_resync_ext_1_svc;
+	break;
+
     default:
 	krb5_klog_syslog(LOG_ERR,
 			 _("RPC unknown request: %d (%s)"),

Modified: trunk/src/kadmin/server/ovsec_kadmd.c
===================================================================
--- trunk/src/kadmin/server/ovsec_kadmd.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/server/ovsec_kadmd.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -306,7 +306,7 @@
      if((ret = kadm5_init(context, "kadmind", NULL,
 			  NULL, &params,
 			  KADM5_STRUCT_VERSION,
-			  KADM5_API_VERSION_2,
+			  KADM5_API_VERSION_3,
 			  db_args,
 		     &global_server_handle)) != KADM5_OK) {
 	  const char *e_txt = krb5_get_error_message (context, ret);

Modified: trunk/src/kadmin/server/server_stubs.c
===================================================================
--- trunk/src/kadmin/server/server_stubs.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/server/server_stubs.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -1598,12 +1598,14 @@
      trunc_name(&slen, &sdots);
      /* okay to cast lengths to int because trunc_name limits max value */
      krb5_klog_syslog(LOG_NOTICE, "Request: kadm5_init, %.*s%s, %s, "
-		      "client=%.*s%s, service=%.*s%s, addr=%s, flavor=%d",
+		      "client=%.*s%s, service=%.*s%s, addr=%s, "
+		      "vers=%d, flavor=%d",
 		      (int)clen, (char *)client_name.value, cdots,
 		      errmsg ? errmsg : "success",
 		      (int)clen, (char *)client_name.value, cdots,
 		      (int)slen, (char *)service_name.value, sdots,
 		      inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
+		      ret.api_version & ~(KADM5_API_VERSION_MASK),
 		      rqstp->rq_cred.oa_flavor);
      if (errmsg != NULL)
 	 krb5_free_error_message(NULL, errmsg);

Modified: trunk/src/kadmin/testing/scripts/init_db
===================================================================
--- trunk/src/kadmin/testing/scripts/init_db	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/testing/scripts/init_db	2009-10-25 16:55:12 UTC (rev 23038)
@@ -103,13 +103,13 @@
 set cmds {
     {kadm5_init $env(SRVTCL) mrroot null \
 	    [config_params {KADM5_CONFIG_REALM} $r] $KADM5_STRUCT_VERSION \
-	    $KADM5_API_VERSION_2 server_handle}
+	    $KADM5_API_VERSION_3 server_handle}
 
-    {kadm5_create_policy $server_handle "test-pol 0 10000 8 2 3 0" \
-	    {KADM5_POLICY KADM5_PW_MIN_LENGTH KADM5_PW_MIN_CLASSES KADM5_PW_MAX_LIFE KADM5_PW_HISTORY_NUM}}
-    {kadm5_create_policy $server_handle "once-a-min 10 0 0 0 0 0" \
+    {kadm5_create_policy $server_handle "test-pol 0 10000 8 2 3 0 2 90 180" \
+	    {KADM5_POLICY KADM5_PW_MIN_LENGTH KADM5_PW_MIN_CLASSES KADM5_PW_MAX_LIFE KADM5_PW_HISTORY_NUM KADM5_PW_MAX_FAILURE KADM5_PW_FAILURE_COUNT_INTERVAL KADM5_PW_LOCKOUT_DURATION}}
+    {kadm5_create_policy $server_handle "once-a-min 10 0 0 0 0 0 0 0 0" \
 	    {KADM5_POLICY KADM5_PW_MIN_LIFE}}
-    {kadm5_create_policy $server_handle "dict-only 0 0 0 0 0 0" \
+    {kadm5_create_policy $server_handle "dict-only 0 0 0 0 0 0 0 0 0" \
 	    {KADM5_POLICY}}
     {kadm5_create_policy $server_handle [simple_policy test-pol-nopw] \
 	    {KADM5_POLICY}}

Modified: trunk/src/kadmin/testing/scripts/start_servers_local
===================================================================
--- trunk/src/kadmin/testing/scripts/start_servers_local	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/testing/scripts/start_servers_local	2009-10-25 16:55:12 UTC (rev 23038)
@@ -83,7 +83,7 @@
 	set q $env(QUALNAME)
 	puts stdout [kadm5_init $env(SRVTCL) mrroot null \
 		[config_params {KADM5_CONFIG_REALM} $r] \
-		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle]
+		$KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 server_handle]
 	puts stdout [kadm5_create_principal $server_handle \
 		[simple_principal host/$q@$r] {KADM5_PRINCIPAL} notathena]
 	puts stdout [kadm5_destroy $server_handle]

Modified: trunk/src/kadmin/testing/tcl/util.t
===================================================================
--- trunk/src/kadmin/testing/tcl/util.t	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/testing/tcl/util.t	2009-10-25 16:55:12 UTC (rev 23038)
@@ -7,7 +7,7 @@
 }
 
 proc simple_policy {name} {
-    return "{$name} 0 0 0 0 0 0"
+    return "{$name} 0 0 0 0 0 0 0 0 0"
 }
 
 proc config_params {masks values} {

Modified: trunk/src/kadmin/testing/util/tcl_kadm5.c
===================================================================
--- trunk/src/kadmin/testing/util/tcl_kadm5.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kadmin/testing/util/tcl_kadm5.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -71,7 +71,10 @@
      {"KADM5_PW_MIN_LENGTH", KADM5_PW_MIN_LENGTH},
      {"KADM5_PW_MIN_CLASSES", KADM5_PW_MIN_CLASSES},
      {"KADM5_PW_HISTORY_NUM", KADM5_PW_HISTORY_NUM},
-     {"KADM5_REF_COUNT", KADM5_REF_COUNT}
+     {"KADM5_REF_COUNT", KADM5_REF_COUNT},
+     {"KADM5_PW_MAX_FAILURE", KADM5_PW_MAX_FAILURE},
+     {"KADM5_PW_FAILURE_COUNT_INTERVAL", KADM5_PW_FAILURE_COUNT_INTERVAL},
+     {"KADM5_PW_LOCKOUT_DURATION", KADM5_PW_LOCKOUT_DURATION},
 };
 
 static struct flagval config_mask_flags[] = {
@@ -1309,6 +1312,7 @@
 	  retcode = TCL_ERROR;
 	  goto finished;
      }
+     princ->n_tl_data = tmp;
 
 finished:
      Tcl_Free((char *) argv);
@@ -1360,6 +1364,15 @@
      sprintf(buf, "%ld", policy->policy_refcnt);
      Tcl_DStringAppendElement(str, buf);
 
+     sprintf(buf, "%d", policy->pw_max_fail);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", policy->pw_failcnt_interval);
+     Tcl_DStringAppendElement(str, buf);
+
+     sprintf(buf, "%d", policy->pw_lockout_duration);
+     Tcl_DStringAppendElement(str, buf);
+
      return str;
 }
 
@@ -1379,8 +1392,8 @@
 	  return tcl_ret;
      }
 
-     if (argc != 7) {
-	  sprintf(interp->result, "wrong # args in policy structure (%d should be 7)",
+     if (argc != 7 && argc != 10) {
+	  sprintf(interp->result, "wrong # args in policy structure (%d should be 7 or 10)",
 		  argc);
 	  retcode = TCL_ERROR;
 	  goto finished;
@@ -1459,6 +1472,32 @@
      }
      policy->policy_refcnt = tmp;
 
+     if (argc == 7) goto finished;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[7], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_max_fail");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_max_fail = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[8], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_failcnt_interval");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_failcnt_interval = tmp;
+
+     if ((tcl_ret = Tcl_GetInt(interp, argv[9], &tmp))
+	 != TCL_OK) {
+	  Tcl_AppendElement(interp, "while parsing pw_lockout_duration");
+	  retcode = TCL_ERROR;
+	  goto finished;
+     }
+     policy->pw_lockout_duration = tmp;
+
 finished:
      Tcl_Free((char *) argv);
      *out_policy = policy;
@@ -2488,6 +2527,8 @@
      Tcl_SetVar(interp, "KADM5_STRUCT_VERSION", buf, TCL_GLOBAL_ONLY);
     (void) sprintf(buf, "%d", KADM5_API_VERSION_2);
      Tcl_SetVar(interp, "KADM5_API_VERSION_2", buf, TCL_GLOBAL_ONLY);
+    (void) sprintf(buf, "%d", KADM5_API_VERSION_3);
+     Tcl_SetVar(interp, "KADM5_API_VERSION_3", buf, TCL_GLOBAL_ONLY);
     (void) sprintf(buf, "%d", KADM5_API_VERSION_MASK);
      Tcl_SetVar(interp, "KADM5_API_VERSION_MASK", buf, TCL_GLOBAL_ONLY);
     (void) sprintf(buf, "%d", KADM5_STRUCT_VERSION_MASK);

Modified: trunk/src/kdc/do_as_req.c
===================================================================
--- trunk/src/kdc/do_as_req.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kdc/do_as_req.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -106,7 +106,6 @@
     krb5_keyblock server_keyblock, client_keyblock;
     krb5_keyblock *mkey_ptr;
     krb5_enctype useenctype;
-    krb5_boolean update_client = 0;
     krb5_data e_data;
     register int i;
     krb5_timestamp until, rtime;
@@ -392,21 +391,6 @@
 	    if (errcode == KRB5KDC_ERR_PREAUTH_FAILED)
 		get_preauth_hint_list(request, &client, &server, &e_data);
 	    
-	    if (kdc_modifies_kdb) {
-		/*
-		 * Note: this doesn't work if you're using slave servers!!!
-		 * It also causes the database to be modified (and thus
-		 * need to be locked) frequently.
-		 */
-		if (client.fail_auth_count < KRB5_MAX_FAIL_COUNT) {
-		    client.fail_auth_count = client.fail_auth_count + 1;
-		    if (client.fail_auth_count == KRB5_MAX_FAIL_COUNT) {
-			client.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
-		    }
-		}
-		client.last_failed = kdc_time;
-	    }
-	    update_client = 1;
 	    status = "PREAUTH_FAILED";
 	    if (vague_errors)
 		errcode = KRB5KRB_ERR_GENERIC;
@@ -620,15 +604,6 @@
     memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
     free(reply.enc_part.ciphertext.data);
 
-    if (kdc_modifies_kdb) {
-	/*
-	 * If we get this far, we successfully did the AS_REQ.
-	 */
-	client.last_success = kdc_time;
-	client.fail_auth_count = 0;
-    }
-    update_client = 1;
-
     log_as_req(from, request, &reply, &client, cname, &server, sname,
 	       authtime, 0, 0, 0);
     did_log = 1;
@@ -648,8 +623,8 @@
 	emsg = krb5_get_error_message(kdc_context, errcode);
 
     if (status) {
-	log_as_req(from, request, &reply, &client, cname, &server, sname, 0,
-		   status, errcode, emsg);
+	log_as_req(from, request, &reply, &client, cname, &server, sname,
+		   authtime, status, errcode, emsg);
 	did_log = 1;
     }
     if (errcode) {
@@ -681,25 +656,8 @@
 	    free(cname);
     if (sname != NULL)
 	    free(sname);
-    if (c_nprincs) {
-	if (kdc_modifies_kdb) {
-	    if (update_client) {
-		krb5_error_code errcode2;
-
-		krb5_db_put_principal(kdc_context, &client, &c_nprincs);
-		/*
-		 * ptooey.  We want krb5_db_sync() or something like that.
-		 */
-		errcode2 = krb5_db_fini(kdc_context);
-		if (errcode2 == 0)
-		    errcode2 = krb5_db_open(kdc_context, db_args,
-					    KRB5_KDB_OPEN_RW|KRB5_KDB_SRV_TYPE_KDC);
-		/* Reset master key */
-		krb5_db_set_mkey(kdc_context, &kdc_active_realm->realm_mkey);
-	    }
-	}
+    if (c_nprincs)
 	krb5_db_free_principal(kdc_context, &client, c_nprincs);
-    }
     if (s_nprincs)
 	krb5_db_free_principal(kdc_context, &server, s_nprincs);
     if (session_key.contents != NULL)

Modified: trunk/src/kdc/extern.c
===================================================================
--- trunk/src/kdc/extern.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kdc/extern.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -38,11 +38,6 @@
 krb5_timestamp kdc_infinity = KRB5_INT32_MAX; /* XXX */
 krb5_rcache	kdc_rcache = (krb5_rcache) NULL;
 krb5_keyblock	psr_key;
-#ifdef KRBCONF_KDC_MODIFIES_KDB
-const int	kdc_modifies_kdb = 1;
-#else
-const int	kdc_modifies_kdb = 0;
-#endif
 krb5_int32	max_dgram_reply_size = MAX_DGRAM_SIZE;
 
 volatile int signal_requests_exit = 0;	/* gets set when signal hits */

Modified: trunk/src/kdc/main.c
===================================================================
--- trunk/src/kdc/main.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/kdc/main.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -381,10 +381,7 @@
     }
 
     /* first open the database  before doing anything */
-    if (kdc_modifies_kdb)
-	kdb_open_flags = KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC;
-    else
-	kdb_open_flags = KRB5_KDB_OPEN_RO | KRB5_KDB_SRV_TYPE_KDC;
+    kdb_open_flags = KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC;
     if ((kret = krb5_db_open(rdp->realm_context, db_args, kdb_open_flags))) {
 	kdc_err(rdp->realm_context, kret,
 		"while initializing database for realm %s", realm);

Modified: trunk/src/lib/kadm5/admin.h
===================================================================
--- trunk/src/lib/kadm5/admin.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/admin.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -112,8 +112,8 @@
 #endif
 #define KADM5_LOAD		0x200000
 
-/* all but KEY_DATA and TL_DATA */
-#define KADM5_PRINCIPAL_NORMAL_MASK 0x01ffff
+/* all but KEY_DATA, TL_DATA, LOAD */
+#define KADM5_PRINCIPAL_NORMAL_MASK 0x41ffff
 
 
 /* kadm5_policy_ent_t */
@@ -123,6 +123,9 @@
 #define KADM5_PW_MIN_CLASSES	0x020000
 #define KADM5_PW_HISTORY_NUM	0x040000
 #define KADM5_REF_COUNT		0x080000
+#define KADM5_PW_MAX_FAILURE		0x100000
+#define KADM5_PW_FAILURE_COUNT_INTERVAL	0x200000
+#define KADM5_PW_LOCKOUT_DURATION	0x400000
 
 /* kadm5_config_params */
 #define KADM5_CONFIG_REALM		0x00000001
@@ -176,6 +179,7 @@
 
 #define KADM5_API_VERSION_MASK	0x12345700
 #define KADM5_API_VERSION_2	(KADM5_API_VERSION_MASK|0x02)
+#define KADM5_API_VERSION_3	(KADM5_API_VERSION_MASK|0x03)
 
 typedef struct _kadm5_principal_ent_t {
 	krb5_principal	principal;
@@ -210,6 +214,11 @@
 	long		pw_min_classes;
 	long		pw_history_num;
 	long		policy_refcnt;
+
+	/* version 3 fields */
+	krb5_kvno	pw_max_fail;
+	krb5_deltat	pw_failcnt_interval;
+	krb5_deltat	pw_lockout_duration;
 } kadm5_policy_ent_rec, *kadm5_policy_ent_t;
 
 /*

Modified: trunk/src/lib/kadm5/admin_internal.h
===================================================================
--- trunk/src/lib/kadm5/admin_internal.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/admin_internal.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -31,7 +31,7 @@
 		return KADM5_BAD_API_VERSION; \
 	if (srvr->api_version < KADM5_API_VERSION_2) \
 		return old_api_version; \
-	if (srvr->api_version > KADM5_API_VERSION_2) \
+	if (srvr->api_version > KADM5_API_VERSION_3) \
 		return new_api_version; \
 }
 

Modified: trunk/src/lib/kadm5/clnt/client_init.c
===================================================================
--- trunk/src/lib/kadm5/clnt/client_init.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/clnt/client_init.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -205,7 +205,7 @@
      handle->destroy_cache = 0;
      handle->context = 0;
      *handle->lhandle = *handle;
-     handle->lhandle->api_version = KADM5_API_VERSION_2;
+     handle->lhandle->api_version = KADM5_API_VERSION_3;
      handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
      handle->lhandle->lhandle = handle->lhandle;
 
@@ -361,6 +361,16 @@
 #endif
 	  goto error;
      }
+     /* Drop down to v2 wire protocol if server does not support v3 */
+     if (r->code == KADM5_NEW_SERVER_API_VERSION &&
+	 handle->api_version == KADM5_API_VERSION_3) {
+	 handle->api_version = KADM5_API_VERSION_2;
+	 r = init_2(&handle->api_version, handle->clnt);
+	 if (r == NULL) {
+	    code = KADM5_RPC_ERROR;
+	    goto error;
+	 }
+     }
      if (r->code) {
 	  code = r->code;
 	  goto error;

Modified: trunk/src/lib/kadm5/kadm_rpc_xdr.c
===================================================================
--- trunk/src/lib/kadm5/kadm_rpc_xdr.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/kadm_rpc_xdr.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -14,6 +14,9 @@
 static bool_t
 _xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
 			     int v);
+static bool_t
+_xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp, int vers);
+
 /*
  * Function: xdr_ui_4
  *
@@ -383,14 +386,14 @@
 bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs,
 				   kadm5_principal_ent_rec *objp)
 {
-     return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_2);
+     return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_3);
 }
 
 static bool_t
 _xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
 			     int v)
 {
-     unsigned int n;
+	unsigned int n;
      
 	if (!xdr_krb5_principal(xdrs, &objp->principal)) {
 		return (FALSE);
@@ -457,11 +460,12 @@
 		       xdr_krb5_key_data_nocontents)) {
 		return (FALSE);
 	}
+
 	return (TRUE);
 }
 
-bool_t
-xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp)
+static bool_t
+_xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp, int vers)
 {
 	if (!xdr_nullstring(xdrs, &objp->policy)) {
 		return (FALSE);
@@ -487,16 +491,35 @@
 	if (!xdr_long(xdrs, &objp->policy_refcnt)) {
 		return (FALSE);
 	}
+	if (vers == KADM5_API_VERSION_3) {
+		if (!xdr_krb5_kvno(xdrs, &objp->pw_max_fail))
+			return (FALSE);
+		if (!xdr_krb5_deltat(xdrs, &objp->pw_failcnt_interval))
+			return (FALSE);
+		if (!xdr_krb5_deltat(xdrs, &objp->pw_lockout_duration))
+			return (FALSE);
+	} else if (xdrs->x_op == XDR_DECODE) {
+		objp->pw_max_fail = 0;
+		objp->pw_failcnt_interval = 0;
+		objp->pw_lockout_duration = 0;
+	}
 	return (TRUE);
 }
 
 bool_t
+xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp)
+{
+	return _xdr_kadm5_policy_ent_rec(xdrs, objp, KADM5_API_VERSION_3);
+}
+
+bool_t
 xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp)
 {
 	if (!xdr_ui_4(xdrs, &objp->api_version)) {
 		return (FALSE);
 	}
-	if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+	if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
+					  objp->api_version)) {
 		return (FALSE);
 	}
 	if (!xdr_long(xdrs, &objp->mask)) {
@@ -514,7 +537,8 @@
 	if (!xdr_ui_4(xdrs, &objp->api_version)) {
 		return (FALSE);
 	}
-	if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+	if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
+					  objp->api_version)) {
 		return (FALSE);
 	}
 	if (!xdr_long(xdrs, &objp->mask)) {
@@ -563,7 +587,8 @@
 	if (!xdr_ui_4(xdrs, &objp->api_version)) {
 		return (FALSE);
 	}
-	if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+	if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
+					  objp->api_version)) {
 		return (FALSE);
 	}
 	if (!xdr_long(xdrs, &objp->mask)) {
@@ -799,7 +824,8 @@
 		return (FALSE);
 	}
 	if(objp->code == KADM5_OK)  {
-		if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+		if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
+						  objp->api_version)) {
 			return (FALSE);
 		}
 	}
@@ -813,7 +839,8 @@
 	if (!xdr_ui_4(xdrs, &objp->api_version)) {
 		return (FALSE);
 	}
-	if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
+	if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec,
+				       objp->api_version)) {
 		return (FALSE);
 	}
 	if (!xdr_long(xdrs, &objp->mask)) {
@@ -840,7 +867,8 @@
 	if (!xdr_ui_4(xdrs, &objp->api_version)) {
 		return (FALSE);
 	}
-	if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
+	if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec,
+				       objp->api_version)) {
 		return (FALSE);
 	}
 	if (!xdr_long(xdrs, &objp->mask)) {
@@ -871,7 +899,8 @@
 		return (FALSE);
 	}
 	if(objp->code == KADM5_OK) {
-	    if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec))
+	    if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec,
+					   objp->api_version))
 		return (FALSE);
 	}
 

Modified: trunk/src/lib/kadm5/server_internal.h
===================================================================
--- trunk/src/lib/kadm5/server_internal.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/server_internal.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -111,12 +111,13 @@
   KADM5_LAST_PWD_CHANGE | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | \
   KADM5_MOD_TIME | KADM5_MOD_NAME | KADM5_KVNO | KADM5_MKVNO | \
   KADM5_AUX_ATTRIBUTES | KADM5_POLICY_CLR | KADM5_POLICY | \
-  KADM5_MAX_RLIFE | KADM5_TL_DATA | KADM5_KEY_DATA)
+  KADM5_MAX_RLIFE | KADM5_TL_DATA | KADM5_KEY_DATA | KADM5_FAIL_AUTH_COUNT )
 
 #define ALL_POLICY_MASK \
  (KADM5_POLICY | KADM5_PW_MAX_LIFE | KADM5_PW_MIN_LIFE | \
   KADM5_PW_MIN_LENGTH | KADM5_PW_MIN_CLASSES | KADM5_PW_HISTORY_NUM | \
-  KADM5_REF_COUNT)
+  KADM5_REF_COUNT | KADM5_PW_MAX_FAILURE | KADM5_PW_FAILURE_COUNT_INTERVAL | \
+  KADM5_PW_LOCKOUT_DURATION )
 
 #define SERVER_CHECK_HANDLE(handle) \
 { \

Modified: trunk/src/lib/kadm5/srv/server_init.c
===================================================================
--- trunk/src/lib/kadm5/srv/server_init.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/srv/server_init.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -273,7 +273,7 @@
 	 return ENOMEM;
     }
     *handle->lhandle = *handle;
-    handle->lhandle->api_version = KADM5_API_VERSION_2;
+    handle->lhandle->api_version = KADM5_API_VERSION_3;
     handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
     handle->lhandle->lhandle = handle->lhandle;
 

Modified: trunk/src/lib/kadm5/srv/server_kdb.c
===================================================================
--- trunk/src/lib/kadm5/srv/server_kdb.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/srv/server_kdb.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -395,6 +395,9 @@
 
     one = 1;
 
+    /* we are always updating TL data */
+    kdb->mask |= KADM5_TL_DATA;
+
     ret = krb5_db_put_principal(handle->context, kdb, &one);
     if (ret)
 	return(ret);

Modified: trunk/src/lib/kadm5/srv/svr_policy.c
===================================================================
--- trunk/src/lib/kadm5/srv/svr_policy.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/srv/svr_policy.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -140,6 +140,26 @@
 	pent.policy_refcnt = 0;
     else
 	pent.policy_refcnt = entry->policy_refcnt;
+
+    if (handle->api_version == KADM5_API_VERSION_3) {
+	if (!(mask & KADM5_PW_MAX_FAILURE))
+	    pent.pw_max_fail = 0;
+	else
+	    pent.pw_max_fail = entry->pw_max_fail;
+	if (!(mask & KADM5_PW_FAILURE_COUNT_INTERVAL))
+	    pent.pw_failcnt_interval = 0;
+	else
+	    pent.pw_failcnt_interval = entry->pw_failcnt_interval;
+	if (!(mask & KADM5_PW_LOCKOUT_DURATION))
+	    pent.pw_lockout_duration = 0;
+	else
+	    pent.pw_lockout_duration = entry->pw_lockout_duration;
+    } else {
+	pent.pw_max_fail = 0;
+	pent.pw_failcnt_interval = 0;
+	pent.pw_lockout_duration = 0;
+    }
+
     if ((ret = krb5_db_create_policy(handle->context, &pent)))
 	return ret;
     else
@@ -248,6 +268,14 @@
     }
     if ((mask & KADM5_REF_COUNT))
 	p->policy_refcnt = entry->policy_refcnt;
+    if (handle->api_version == KADM5_API_VERSION_3) {
+	if ((mask & KADM5_PW_MAX_FAILURE))
+	    p->pw_max_fail = entry->pw_max_fail;
+	if ((mask & KADM5_PW_FAILURE_COUNT_INTERVAL))
+	    p->pw_failcnt_interval = entry->pw_failcnt_interval;
+	if ((mask & KADM5_PW_LOCKOUT_DURATION))
+	    p->pw_lockout_duration = entry->pw_lockout_duration;
+    }
     ret = krb5_db_put_policy(handle->context, p);
     krb5_db_free_policy(handle->context, p);
     return ret;
@@ -286,6 +314,11 @@
     entry->pw_min_classes = t->pw_min_classes;
     entry->pw_history_num = t->pw_history_num;
     entry->policy_refcnt = t->policy_refcnt;
+    if (handle->api_version == KADM5_API_VERSION_3) {
+	entry->pw_max_fail = t->pw_max_fail;
+	entry->pw_failcnt_interval = t->pw_failcnt_interval;
+	entry->pw_lockout_duration = t->pw_lockout_duration;
+    }
     krb5_db_free_policy(handle->context, t);
 
     return KADM5_OK;

Modified: trunk/src/lib/kadm5/srv/svr_principal.c
===================================================================
--- trunk/src/lib/kadm5/srv/svr_principal.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/srv/svr_principal.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -650,8 +650,6 @@
 	 kdb.pw_expiration = entry->pw_expiration;
     if (mask & KADM5_MAX_RLIFE)
 	 kdb.max_renewable_life = entry->max_renewable_life;
-    if (mask & KADM5_FAIL_AUTH_COUNT)
-	 kdb.fail_auth_count = entry->fail_auth_count;
 
     if((mask & KADM5_KVNO)) {
 	 for (i = 0; i < kdb.n_key_data; i++)
@@ -674,6 +672,20 @@
 	 }
     }
 
+    /*
+     * Setting entry->fail_auth_count to 0 can be used to manually unlock
+     * an account. It is not possible to set fail_auth_count to any other
+     * value using kadmin.
+     */
+    if (mask & KADM5_FAIL_AUTH_COUNT) {
+	if (entry->fail_auth_count != 0) {
+	    ret = KADM5_BAD_SERVER_PARAMS;
+	    goto done;
+	}
+
+	kdb.fail_auth_count = 0;
+    }
+
     /* let the mask propagate to the database provider */
     kdb.mask = mask;
 
@@ -1443,8 +1455,13 @@
     if (ret)
 	goto done;
 
+    /* unlock principal on this KDC */
+    kdb.fail_auth_count = 0;
+
     /* key data and attributes changed, let the database provider know */
-    kdb.mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES /* | KADM5_CPW_FUNCTION */;
+    kdb.mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES |
+	       KADM5_FAIL_AUTH_COUNT;
+	       /* | KADM5_CPW_FUNCTION */
 
     if ((ret = kdb_put_entry(handle, &kdb, &adb)))
 	goto done;
@@ -1576,7 +1593,10 @@
     if (ret)
 	 goto done;
 
-    if (keyblocks) {
+    /* unlock principal on this KDC */
+    kdb.fail_auth_count = 0;
+
+   if (keyblocks) {
 	ret = decrypt_key_data(handle->context, act_mkey,
 			       kdb.n_key_data, kdb.key_data,
 			       keyblocks, n_keys);
@@ -1585,7 +1605,8 @@
     }
 
     /* key data changed, let the database provider know */
-    kdb.mask = KADM5_KEY_DATA /* | KADM5_RANDKEY_USED */;
+    kdb.mask = KADM5_KEY_DATA | KADM5_FAIL_AUTH_COUNT;
+	       /* | KADM5_RANDKEY_USED */;
 
     if ((ret = kdb_put_entry(handle, &kdb, &adb)))
 	goto done;
@@ -1753,6 +1774,9 @@
     if (ret)
 	 goto done;
 
+    /* unlock principal on this KDC */
+    kdb.fail_auth_count = 0;
+
     if ((ret = kdb_put_entry(handle, &kdb, &adb)))
 	goto done;
 
@@ -1990,6 +2014,9 @@
     if ((ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now)))
         goto done;
 
+    /* unlock principal on this KDC */
+    kdb.fail_auth_count = 0;
+
     if ((ret = kdb_put_entry(handle, &kdb, &adb)))
 	goto done;
 

Modified: trunk/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp
===================================================================
--- trunk/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp	2009-10-25 16:55:12 UTC (rev 23038)
@@ -42,11 +42,12 @@
 		{KADM5_LAST_FAILED}
     } $origtest] "BAD_MASK"
 
-    test "modify-principal 103"
-    one_line_fail_test [format {
-	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
-		{KADM5_FAIL_AUTH_COUNT}
-    } $origtest] "BAD_MASK"
+#    This is now permitted to reset lockout count
+#    test "modify-principal 103"
+#    one_line_fail_test [format {
+#	kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+#		{KADM5_FAIL_AUTH_COUNT}
+#    } $origtest] "BAD_MASK"
 
     test "modify-principal 103.5"
     one_line_fail_test [format {

Copied: trunk/src/lib/kadm5/unit-test/api.3 (from rev 23037, users/lhoward/lockout2/src/lib/kadm5/unit-test/api.3)

Modified: trunk/src/lib/kadm5/unit-test/config/unix.exp
===================================================================
--- trunk/src/lib/kadm5/unit-test/config/unix.exp	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/config/unix.exp	2009-10-25 16:55:12 UTC (rev 23038)
@@ -157,7 +157,7 @@
 		eof { perror "EOF setting API varibles"}
 		timeout { perror "timeout setting API varibles"}
 	}
-	send "set current_api_version \[expr \$KADM5_API_VERSION_2 &~ \$KADM5_API_VERSION_MASK\]\n"
+	send "set current_api_version \[expr \$KADM5_API_VERSION_3 &~ \$KADM5_API_VERSION_MASK\]\n"
 	expect {
 		-re "$prompt$" {}
 		eof { perror "EOF setting API varibles"}

Modified: trunk/src/lib/kadm5/unit-test/destroy-test.c
===================================================================
--- trunk/src/lib/kadm5/unit-test/destroy-test.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/destroy-test.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -27,7 +27,7 @@
      }
      for(x = 0; x < TEST_NUM; x++) {
 	ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, 0,
-			 KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+			 KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL,
 			 &server_handle);
 	if(ret != KADM5_OK) {
 	    com_err("test", ret, "init");

Modified: trunk/src/lib/kadm5/unit-test/handle-test.c
===================================================================
--- trunk/src/lib/kadm5/unit-test/handle-test.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/handle-test.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -25,7 +25,7 @@
     kadm5_init_krb5_context(&context);
      
     ret = kadm5_init(context, "admin/none", "admin", KADM5_ADMIN_SERVICE, NULL,
-		     KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+		     KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL,
 		     &server_handle);
     if(ret != KADM5_OK) {
 	com_err("test", ret, "init");

Modified: trunk/src/lib/kadm5/unit-test/init-test.c
===================================================================
--- trunk/src/lib/kadm5/unit-test/init-test.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/init-test.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -20,7 +20,7 @@
 	 exit(1);
      }
      ret = kadm5_init(context, "admin", "admin", NULL, &params,
-		      KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+		      KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL,
 		      &server_handle);
      if (ret == KADM5_RPC_ERROR)
 	  exit(0);

Modified: trunk/src/lib/kadm5/unit-test/iter-test.c
===================================================================
--- trunk/src/lib/kadm5/unit-test/iter-test.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/iter-test.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -22,7 +22,7 @@
 	 exit(1);
      }
      ret = kadm5_init("admin", "admin", KADM5_ADMIN_SERVICE, 0,
-		      KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+		      KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL,
 		      &server_handle);
      if (ret != KADM5_OK) {
 	  com_err("iter-test", ret, "while initializing");

Modified: trunk/src/lib/kadm5/unit-test/lib/lib.t
===================================================================
--- trunk/src/lib/kadm5/unit-test/lib/lib.t	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/lib/lib.t	2009-10-25 16:55:12 UTC (rev 23038)
@@ -19,7 +19,7 @@
 	set lib_pid [api_start]
 	if {! [cmd {
 	    kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
-		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+		    $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
 		    lib_handle
 	}]} {
 	    perror "$test: unexpected failure in init"

Modified: trunk/src/lib/kadm5/unit-test/randkey-test.c
===================================================================
--- trunk/src/lib/kadm5/unit-test/randkey-test.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/randkey-test.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -23,7 +23,7 @@
 
      krb5_parse_name(context, "testuser", &tprinc);
      ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL,
-		      KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+		      KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL,
 		      &server_handle);
      if(ret != KADM5_OK) {
 	com_err("test", ret, "init");

Modified: trunk/src/lib/kadm5/unit-test/setkey-test.c
===================================================================
--- trunk/src/lib/kadm5/unit-test/setkey-test.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kadm5/unit-test/setkey-test.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -119,7 +119,7 @@
   }
 
   ret = kadm5_init(context, authprinc, NULL, KADM5_ADMIN_SERVICE, NULL,
-		   KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
+		   KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL,
 		   &handle);
   if (ret) {
     com_err(whoami, ret, "while initializing connection");

Modified: trunk/src/lib/kdb/iprop.x
===================================================================
--- trunk/src/lib/kdb/iprop.x	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kdb/iprop.x	2009-10-25 16:55:12 UTC (rev 23038)
@@ -219,5 +219,11 @@
 		 */
 		kdb_fullresync_result_t
 		IPROP_FULL_RESYNC(void) = 2;
+
+		/*
+		 * Full resync with version marker
+		 */
+		kdb_fullresync_result_t
+		IPROP_FULL_RESYNC_EXT(uint32_t) = 3;
 	} = 1;
 } = 100423;

Modified: trunk/src/lib/kdb/kdb_convert.c
===================================================================
--- trunk/src/lib/kdb/kdb_convert.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/lib/kdb/kdb_convert.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -44,6 +44,7 @@
  */
 static void
 find_changed_attrs(krb5_db_entry *current, krb5_db_entry *new,
+		   krb5_boolean exclude_nra,
 		   kdbe_attr_type_t *attrs, int *nattrs)
 {
     int i = 0, j = 0;
@@ -65,14 +66,16 @@
     if (current->pw_expiration != new->pw_expiration)
 	attrs[i++] = AT_PW_EXP;
 
-    if (current->last_success != new->last_success)
-	attrs[i++] = AT_LAST_SUCCESS;
+    if (!exclude_nra) {
+	if (current->last_success != new->last_success)
+	    attrs[i++] = AT_LAST_SUCCESS;
 
-    if (current->last_failed != new->last_failed)
-	attrs[i++] = AT_LAST_FAILED;
+	if (current->last_failed != new->last_failed)
+	    attrs[i++] = AT_LAST_FAILED;
 
-    if (current->fail_auth_count != new->fail_auth_count)
-	attrs[i++] = AT_FAIL_AUTH_COUNT;
+	if (current->fail_auth_count != new->fail_auth_count)
+	    attrs[i++] = AT_FAIL_AUTH_COUNT;
+    }
 
     if ((current->princ->type == new->princ->type) &&
 	(current->princ->length == new->princ->length)) {
@@ -128,7 +131,6 @@
 		break;
 	    }
 	}
-
     } else {
 	attrs[i++] = AT_TL_DATA;
     }
@@ -307,6 +309,8 @@
     kdb_incr_update_t *upd;
     krb5_db_entry *ent;
     int kadm_data_yes;
+    /* always exclude non-replicated attributes, for now */
+    krb5_boolean exclude_nra = TRUE;
 
     if ((updates == NULL) || (entries == NULL))
 	return (KRB5KRB_ERR_GENERIC);
@@ -320,6 +324,10 @@
 	kadm_data_yes = 0;
 	attr_types = NULL;
 
+	/*
+	 * XXX we rely on the good behaviour of the database not to
+	 * exceed this limit.
+	 */
 	if ((upd->kdb_update.kdbe_t_val = (kdbe_val_t *)
 	     malloc(MAXENTRY_SIZE)) == NULL) {
 	    return (ENOMEM);
@@ -359,7 +367,7 @@
 		nattrs++;
 	    }
 	} else {
-	    find_changed_attrs(&curr, ent, attr_types, &nattrs);
+	    find_changed_attrs(&curr, ent, exclude_nra, attr_types, &nattrs);
 
 	    krb5_db_free_principal(context, &curr, nprincs);
 	}
@@ -413,7 +421,7 @@
 		break;
 
 	    case AT_LAST_SUCCESS:
-		if (ent->last_success >= 0) {
+		if (!exclude_nra && ent->last_success >= 0) {
 		    ULOG_ENTRY_TYPE(upd, ++final).av_type =
 			AT_LAST_SUCCESS;
 		    ULOG_ENTRY(upd,
@@ -423,7 +431,7 @@
 		break;
 
 	    case AT_LAST_FAILED:
-		if (ent->last_failed >= 0) {
+		if (!exclude_nra && ent->last_failed >= 0) {
 		    ULOG_ENTRY_TYPE(upd, ++final).av_type =
 			AT_LAST_FAILED;
 		    ULOG_ENTRY(upd,
@@ -433,7 +441,7 @@
 		break;
 
 	    case AT_FAIL_AUTH_COUNT:
-		if (ent->fail_auth_count >= (krb5_kvno)0) {
+		if (!exclude_nra && ent->fail_auth_count >= (krb5_kvno)0) {
 		    ULOG_ENTRY_TYPE(upd, ++final).av_type =
 			AT_FAIL_AUTH_COUNT;
 		    ULOG_ENTRY(upd,
@@ -611,6 +619,7 @@
     int k;
     krb5_db_entry *ent;
     kdb_incr_update_t *upd;
+    int slave;
 
     if ((updates == NULL) || (entries == NULL))
 	return (KRB5KRB_ERR_GENERIC);
@@ -618,6 +627,9 @@
     ent = entries;
     upd = updates;
 
+    slave = (context->kdblog_context != NULL) &&
+	    (context->kdblog_context->iproprole == IPROP_SLAVE);
+
     for (k = 0; k < nentries; k++) {
 	krb5_principal mod_princ = NULL;
 	int i, j, cnt = 0, mod_time = 0, nattrs, nprincs = 0;
@@ -692,15 +704,18 @@
 		break;
 
 	    case AT_LAST_SUCCESS:
-		ent->last_success = (krb5_timestamp) u.av_last_success;
+		if (!slave)
+		    ent->last_success = (krb5_timestamp) u.av_last_success;
 		break;
 
 	    case AT_LAST_FAILED:
-		ent->last_failed = (krb5_timestamp) u.av_last_failed;
+		if (!slave)
+		    ent->last_failed = (krb5_timestamp) u.av_last_failed;
 		break;
 
 	    case AT_FAIL_AUTH_COUNT:
-		ent->fail_auth_count = (krb5_kvno) u.av_fail_auth_count;
+		if (!slave)
+		    ent->fail_auth_count = (krb5_kvno) u.av_fail_auth_count;
 		break;
 
 	    case AT_PRINC:
@@ -765,34 +780,34 @@
 		}
 		break;
 
-	    case AT_TL_DATA:
+	    case AT_TL_DATA: {
+		int t;
+
 		cnt = u.av_tldata.av_tldata_len;
-		newtl = malloc(cnt * sizeof (krb5_tl_data));
-		(void) memset(newtl, 0, (cnt * sizeof (krb5_tl_data)));
+		newtl = calloc(cnt, sizeof (krb5_tl_data));
 		if (newtl == NULL)
 		    return (ENOMEM);
 
-		for (j = 0; j < cnt; j++) {
-		    newtl[j].tl_data_type = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_type;
-		    newtl[j].tl_data_length = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_data.tl_data_len;
-		    newtl[j].tl_data_contents = NULL;
-		    newtl[j].tl_data_contents = malloc(newtl[j].tl_data_length * sizeof (krb5_octet));
-		    if (newtl[j].tl_data_contents == NULL)
+		for (j = 0, t = 0; j < cnt; j++) {
+		    newtl[t].tl_data_type = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_type;
+		    newtl[t].tl_data_length = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_data.tl_data_len;
+		    newtl[t].tl_data_contents = malloc(newtl[t].tl_data_length * sizeof (krb5_octet));
+		    if (newtl[t].tl_data_contents == NULL)
 			/* XXX Memory leak: newtl
 			   and previously
 			   allocated elements.  */
 			return (ENOMEM);
 
-		    (void) memset(newtl[j].tl_data_contents, 0, (newtl[j].tl_data_length * sizeof (krb5_octet)));
-		    (void) memcpy(newtl[j].tl_data_contents, u.av_tldata.av_tldata_val[j].tl_data.tl_data_val, newtl[j].tl_data_length);
-		    newtl[j].tl_data_next = NULL;
-		    if (j > 0)
-			newtl[j - 1].tl_data_next = &newtl[j];
+		    (void) memcpy(newtl[t].tl_data_contents, u.av_tldata.av_tldata_val[t].tl_data.tl_data_val, newtl[t].tl_data_length);
+		    newtl[t].tl_data_next = NULL;
+		    if (t > 0)
+			newtl[t - 1].tl_data_next = &newtl[t];
+		    t++;
 		}
 
 		if ((ret = krb5_dbe_update_tl_data(context, ent, newtl)))
 		    return (ret);
-		for (j = 0; j < cnt; j++)
+		for (j = 0; j < t; j++)
 		    if (newtl[j].tl_data_contents) {
 			free(newtl[j].tl_data_contents);
 			newtl[j].tl_data_contents = NULL;
@@ -803,7 +818,7 @@
 		}
 		break;
 /* END CSTYLED */
-
+	    }
 	    case AT_PW_LAST_CHANGE:
 		if ((ret = krb5_dbe_update_last_pwd_change(context, ent,
 							   u.av_pw_last_change)))

Modified: trunk/src/plugins/kdb/db2/Makefile.in
===================================================================
--- trunk/src/plugins/kdb/db2/Makefile.in	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/db2/Makefile.in	2009-10-25 16:55:12 UTC (rev 23038)
@@ -25,7 +25,7 @@
 DB_LIB		= @DB_LIB@
 KDB5_DB_LIB	= @KDB5_DB_LIB@
 DB_DEPLIB	= $(DB_DEPLIB- at DB_VERSION@)
-DB_DEPLIB-k5	= $(TOPLIBD)/libdb$(DEPLIBEXT)
+DB_DEPLIB-k5	= $(TOPLIBD)/libdb$(DEPLIBEXT) $(KADMSRV_DEPLIBS)
 DB_DEPLIB-sys	=
 
 LIBBASE=db2
@@ -39,7 +39,7 @@
 	$(GSSRPC_DEPLIBS) \
 	$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
 	$(TOPLIBD)/libkrb5$(SHLIBEXT)
-SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lcom_err -lk5crypto $(KDB5_DB_LIB) $(SUPPORT_LIB) $(LIBS) @DB_EXTRA_LIBS@
+SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lcom_err -lk5crypto $(KDB5_DB_LIB) $(KADMSRV_LIBS) $(SUPPORT_LIB) $(LIBS) @DB_EXTRA_LIBS@
 
 SHLIB_DIRS=-L$(TOPLIBD)
 SHLIB_RDIRS=$(KRB5_LIBDIR)
@@ -56,8 +56,10 @@
 	$(srcdir)/adb_openclose.c \
 	$(srcdir)/adb_policy.c \
 	$(srcdir)/kdb_db2.c \
+	$(srcdir)/kdb_ext.c \
 	$(srcdir)/pol_xdr.c \
-	$(srcdir)/db2_exp.c
+	$(srcdir)/db2_exp.c \
+	$(srcdir)/lockout.c
 
 STOBJLISTS=OBJS.ST $(DBOBJLISTS)
 STLIBOBJS= \
@@ -65,8 +67,10 @@
 	adb_openclose.o \
 	adb_policy.o \
 	kdb_db2.o \
+	kdb_ext.o \
 	pol_xdr.o \
-	db2_exp.o
+	db2_exp.o \
+	lockout.o
 
 all-unix:: all-liblinks
 install-unix:: install-libs

Modified: trunk/src/plugins/kdb/db2/db2_exp.c
===================================================================
--- trunk/src/plugins/kdb/db2/db2_exp.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/db2/db2_exp.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -197,6 +197,13 @@
 	( krb5_context kcontext, char *conf_section, char **db_args ),
 	(kcontext, conf_section, db_args));
 
+WRAP_K (krb5_db2_invoke,
+	(krb5_context kcontext,
+	 unsigned int method,
+	 const krb5_data *request,
+	 krb5_data *response),
+	(kcontext, method, request, response));
+
 static krb5_error_code
 hack_init ()
 {
@@ -256,5 +263,6 @@
   /* get_master_key_list */	    	       wrap_krb5_db2_db_get_mkey_list,
   /* blah blah blah */ 0,0,0,0,0,0,0,0,
   /* promote_db */			       wrap_krb5_db2_promote_db,
-  0,0,0,
+  0, 0,
+  /* invoke */				       wrap_krb5_db2_invoke
 };

Modified: trunk/src/plugins/kdb/db2/kdb_db2.c
===================================================================
--- trunk/src/plugins/kdb/db2/kdb_db2.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/db2/kdb_db2.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -1,7 +1,7 @@
 /*
  * lib/kdb/kdb_db2.c
  *
- * Copyright 1997,2006,2007,2008 by the Massachusetts Institute of Technology.
+ * Copyright 1997,2006,2007-2009 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -68,8 +68,6 @@
 
 #define KDB_DB2_DATABASE_NAME "database_name"
 
-#include "kdb_db2.h"
-
 static char *gen_dbsuffix(char *, char *);
 
 static krb5_error_code krb5_db2_db_start_update(krb5_context);
@@ -774,7 +772,7 @@
     char   *filename;
     struct stat statb;
     int     nb, fd;
-    unsigned int j;
+    int	    j;
     off_t   pos;
     char    buf[BUFSIZ];
     char    zbuf[BUFSIZ];
@@ -1315,6 +1313,9 @@
 	else if (!opt && !strcmp(val, "temporary") ) {
 	    tempdb = 1;
 	}
+	else if (!opt && !strcmp(val, "merge_nra")) {
+	    ;
+	}
 	/* ignore hash argument. Might have been passed from create */
 	else if (!opt || strcmp(opt, "hash")) {
 	    krb5_set_error_message(kcontext, EINVAL,
@@ -1394,8 +1395,9 @@
 	}
 	else if (!opt && !strcmp(val, "temporary")) {
 	    tempdb = 1;
-	}
-	else if (opt && !strcmp(opt, "hash")) {
+	} else if (!opt && !strcmp(val, "merge_nra")) {
+	    ;
+	} else if (opt && !strcmp(opt, "hash")) {
 	    flags = KRB5_KDB_CREATE_HASH;
 	} else {
 	    krb5_set_error_message(kcontext, EINVAL,
@@ -1563,7 +1565,7 @@
     krb5_db2_context *db_ctx;
     kdb5_dal_handle *dal_handle;
 
-        if (!k5db2_inited(kcontext))
+    if (!k5db2_inited(kcontext))
 	return KRB5_KDB_DBNOTINITED;
 
     dal_handle = kcontext->dal_handle;
@@ -1679,6 +1681,8 @@
     krb5_error_code status = 0;
     char *db_name = NULL;
     char *temp_db_name = NULL;
+    char **db_argp;
+    int merge_nra = 0;
 
     krb5_clear_error_message (kcontext);
 
@@ -1699,7 +1703,14 @@
 	goto clean_n_exit;
     }
 
-    status = krb5_db2_db_rename (kcontext, temp_db_name, db_name);
+    for (db_argp = db_args; *db_argp; db_argp++) {
+	if (!strcmp(*db_argp, "merge_nra")) {
+	    merge_nra++;
+	    break;
+	}
+    }
+
+    status = krb5_db2_db_rename (kcontext, temp_db_name, db_name, merge_nra);
     if (status)
 	goto clean_n_exit;
 
@@ -1711,6 +1722,154 @@
     return status;
 }
 
+/*
+ * Merge non-replicated attributes from src into dst, setting
+ * changed to non-zero if dst was changed.
+ *
+ * Non-replicated attributes are: last_success, last_failed,
+ * fail_auth_count, and any negative TL data values.
+ */
+static krb5_error_code
+krb5_db2_merge_principal(krb5_context kcontext,
+			 krb5_db_entry *src,
+			 krb5_db_entry *dst,
+			 int *changed)
+{
+    *changed = 0;
+
+    if (dst->last_success != src->last_success) {
+	dst->last_success = src->last_success;
+	(*changed)++;
+    }
+
+    if (dst->last_failed != src->last_failed) {
+	dst->last_failed = src->last_failed;
+	(*changed)++;
+    }
+
+    if (dst->fail_auth_count != src->fail_auth_count) {
+	dst->fail_auth_count = src->fail_auth_count;
+	(*changed)++;
+    }
+
+    return 0;
+}
+
+struct nra_context {
+    krb5_context kcontext;
+    krb5_db2_context *db_context;
+};
+
+/*
+ * Iteration callback merges non-replicated attributes from
+ * old database.
+ */
+static krb5_error_code
+krb5_db2_merge_nra_iterator(krb5_pointer ptr, krb5_db_entry *entry)
+{
+    struct nra_context *nra = (struct nra_context *)ptr;
+    kdb5_dal_handle *dal_handle = nra->kcontext->dal_handle;
+    krb5_error_code retval;
+    int n_entries = 0, changed;
+    krb5_db_entry s_entry;
+    krb5_boolean more;
+    krb5_db2_context *dst_db;
+
+    memset(&s_entry, 0, sizeof(s_entry));
+
+    dst_db = dal_handle->db_context;
+    dal_handle->db_context = nra->db_context;
+
+    /* look up the new principal in the old DB */
+    retval = krb5_db2_db_get_principal(nra->kcontext,
+				       entry->princ,
+				       &s_entry,
+				       &n_entries,
+				       &more);
+    if (retval != 0 || n_entries == 0) {
+	/* principal may be newly created, so ignore */
+	dal_handle->db_context = dst_db;
+	return 0;
+    }
+
+    /* merge non-replicated attributes from the old entry in */
+    krb5_db2_merge_principal(nra->kcontext, &s_entry, entry, &changed);
+
+    dal_handle->db_context = dst_db;
+
+    /* if necessary, commit the modified new entry to the new DB */
+    if (changed) {
+	retval = krb5_db2_db_put_principal(nra->kcontext,
+					   entry,
+					   &n_entries,
+					   NULL);
+    } else {
+	retval = 0;
+    }
+
+    return retval;
+}
+
+/*
+ * Merge non-replicated attributes (that is, lockout-related
+ * attributes and negative TL data types) from the old database
+ * into the new one.
+ *
+ * Note: src_db is locked on success.
+ */
+static krb5_error_code
+krb5_db2_begin_nra_merge(krb5_context kcontext,
+			 krb5_db2_context *src_db,
+			 krb5_db2_context *dst_db)
+{
+    krb5_error_code retval;
+    kdb5_dal_handle *dal_handle = kcontext->dal_handle;
+    struct nra_context nra;
+
+    nra.kcontext = kcontext;
+    nra.db_context = dst_db;
+
+    assert(dal_handle->db_context == dst_db);
+    dal_handle->db_context = src_db;
+
+    retval = krb5_db2_db_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE);
+    if (retval) {
+	dal_handle->db_context = dst_db;
+	return retval;
+    }
+
+    retval = krb5_db2_db_iterate_ext(kcontext,
+				     krb5_db2_merge_nra_iterator,
+				     &nra,
+				     0,
+				     0);
+    if (retval != 0)
+	(void) krb5_db2_db_unlock(kcontext);
+
+    dal_handle->db_context = dst_db;
+
+    return retval;
+}
+
+/*
+ * Finish merge of non-replicated attributes by unlocking
+ * src_db.
+ */
+static krb5_error_code
+krb5_db2_end_nra_merge(krb5_context kcontext,
+		       krb5_db2_context *src_db,
+		       krb5_db2_context *dst_db)
+{
+    krb5_error_code retval;
+    kdb5_dal_handle *dal_handle = kcontext->dal_handle;
+
+    dal_handle->db_context = src_db;
+    retval = krb5_db2_db_unlock(kcontext);
+    dal_handle->db_context = dst_db;
+
+    return retval;
+}
+
 /* Retrieved from pre-DAL code base.  */
 /*
  * "Atomically" rename the database in a way that locks out read
@@ -1723,12 +1882,12 @@
  * have to go through the same stuff that we went through up in db_destroy.
  */
 krb5_error_code
-krb5_db2_db_rename(context, from, to)
+krb5_db2_db_rename(context, from, to, merge_nra)
     krb5_context context;
     char *from;
     char *to;
+    int merge_nra;
 {
-    DB *db;
     char *fromok;
     krb5_error_code retval;
     krb5_db2_context *s_context, *db_ctx;
@@ -1745,13 +1904,10 @@
      * files must exist because krb5_db2_db_lock, called below,
      * will fail otherwise.
      */
-    db = k5db2_dbopen(db_ctx, to, O_RDWR|O_CREAT, 0600, 0);
-    if (db == NULL) {
-	retval = errno;
+    retval = krb5_db2_db_create(context, to, 0);
+    if (retval != 0 && retval != EEXIST)
 	goto errout;
-    }
-    else
-	(*db->close)(db);
+
     /*
      * Set the database to the target, so that other processes sharing
      * the target will stop their activity, and notice the new database.
@@ -1764,25 +1920,6 @@
     if (retval)
 	goto errout;
 
-    {
-	/* Ugly brute force hack.
-
-	   Should be going through nice friendly helper routines for
-	   this, but it's a mess of jumbled so-called interfaces right
-	   now.  */
-	char    policy[2048], new_policy[2048];
-	assert (strlen(db_ctx->db_name) < 2000);
-	snprintf(policy, sizeof(policy), "%s.kadm5", db_ctx->db_name);
-	snprintf(new_policy, sizeof(new_policy),
-		 "%s~.kadm5", db_ctx->db_name);
-	if (0 != rename(new_policy, policy)) {
-	    retval = errno;
-	    goto errout;
-	}
-	strlcat(new_policy, ".lock",sizeof(new_policy));
-	(void) unlink(new_policy);
-    }
-
     db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, KDB2_LOCK_EXT);
     if (db_ctx->db_lf_name == NULL) {
 	retval = ENOMEM;
@@ -1813,6 +1950,11 @@
     if ((retval = krb5_db2_db_start_update(context)))
 	goto errfromok;
 
+    if (merge_nra) {
+	if ((retval = krb5_db2_begin_nra_merge(context, s_context, db_ctx)))
+	    goto errfromok;
+    }
+
     if (rename(from, to)) {
 	retval = errno;
 	goto errfromok;
@@ -1821,7 +1963,35 @@
 	retval = errno;
 	goto errfromok;
     }
+
+    if (merge_nra) {
+	krb5_db2_end_nra_merge(context, s_context, db_ctx);
+    }
+
     retval = krb5_db2_db_end_update(context);
+    if (retval)
+	goto errfromok;
+
+    {
+	/* XXX moved so that NRA merge works */
+	/* Ugly brute force hack.
+
+	   Should be going through nice friendly helper routines for
+	   this, but it's a mess of jumbled so-called interfaces right
+	   now.  */
+	char    policy[2048], new_policy[2048];
+	assert (strlen(db_ctx->db_name) < 2000);
+	snprintf(policy, sizeof(policy), "%s.kadm5", db_ctx->db_name);
+	snprintf(new_policy, sizeof(new_policy),
+		 "%s~.kadm5", db_ctx->db_name);
+	if (0 != rename(new_policy, policy)) {
+	    retval = errno;
+	    goto errfromok;
+	}
+	strlcat(new_policy, ".lock",sizeof(new_policy));
+	(void) unlink(new_policy);
+    }
+
 errfromok:
     free_dbsuffix(fromok);
 errout:
@@ -1839,3 +2009,4 @@
 
     return retval;
 }
+

Modified: trunk/src/plugins/kdb/db2/kdb_db2.h
===================================================================
--- trunk/src/plugins/kdb/db2/kdb_db2.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/db2/kdb_db2.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -71,7 +71,8 @@
 krb5_error_code krb5_db2_db_rename 
 	(krb5_context,
 		   char *,
-		   char * );
+		   char *,
+		   int );
 krb5_error_code krb5_db2_db_get_principal 
 	(krb5_context,
 		   krb5_const_principal,
@@ -219,4 +220,23 @@
 /* Thread-safety wrapper slapped on top of original implementation.  */
 extern k5_mutex_t *krb5_db2_mutex;
 
+/* lockout */
+krb5_error_code
+krb5_db2_lockout_check_policy(krb5_context context,
+                              krb5_db_entry *entry,
+                              krb5_timestamp stamp);
+
+krb5_error_code
+krb5_db2_lockout_audit(krb5_context context,
+                       krb5_db_entry *entry,
+                       krb5_timestamp stamp,
+                       krb5_error_code status);
+
+/* methods */
+krb5_error_code
+krb5_db2_invoke(krb5_context context,
+                unsigned int method,
+                const krb5_data *req,
+                krb5_data *rep);
+
 #endif /* KRB5_KDB_DB2_H */

Copied: trunk/src/plugins/kdb/db2/kdb_ext.c (from rev 23037, users/lhoward/lockout2/src/plugins/kdb/db2/kdb_ext.c)

Copied: trunk/src/plugins/kdb/db2/lockout.c (from rev 23037, users/lhoward/lockout2/src/plugins/kdb/db2/lockout.c)

Modified: trunk/src/plugins/kdb/db2/pol_xdr.c
===================================================================
--- trunk/src/plugins/kdb/db2/pol_xdr.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/db2/pol_xdr.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -51,14 +51,27 @@
      return FALSE;
 }
                                                                                                                             
+static int
+osa_policy_min_vers(osa_policy_ent_t objp)
+{
+    int vers;
 
+    if (objp->pw_max_fail ||
+        objp->pw_failcnt_interval ||
+        objp->pw_lockout_duration)
+        vers = OSA_ADB_POLICY_VERSION_2;
+    else
+        vers = OSA_ADB_POLICY_VERSION_1;
 
+    return vers;
+}
+
 bool_t
 xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp)
 {
     switch (xdrs->x_op) {
     case XDR_ENCODE:
-	 objp->version = OSA_ADB_POLICY_VERSION_1;
+	 objp->version = osa_policy_min_vers(objp);
 	 /* fall through */
     case XDR_FREE:
 	 if (!xdr_int(xdrs, &objp->version))
@@ -67,7 +80,8 @@
     case XDR_DECODE:
 	 if (!xdr_int(xdrs, &objp->version))
 	      return FALSE;
-	 if (objp->version != OSA_ADB_POLICY_VERSION_1)
+	 if (objp->version != OSA_ADB_POLICY_VERSION_1 &&
+             objp->version != OSA_ADB_POLICY_VERSION_2)
 	      return FALSE;
 	 break;
     }
@@ -86,5 +100,13 @@
 	return (FALSE);
     if (!xdr_u_int32(xdrs, &objp->policy_refcnt))
 	return (FALSE);
+    if (objp->version > OSA_ADB_POLICY_VERSION_1) {
+        if (!xdr_u_int32(xdrs, &objp->pw_max_fail))
+	    return (FALSE);
+        if (!xdr_u_int32(xdrs, &objp->pw_failcnt_interval))
+	    return (FALSE);
+        if (!xdr_u_int32(xdrs, &objp->pw_lockout_duration))
+	    return (FALSE);
+    }
     return (TRUE);
 }

Modified: trunk/src/plugins/kdb/db2/policy_db.h
===================================================================
--- trunk/src/plugins/kdb/db2/policy_db.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/db2/policy_db.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -39,6 +39,7 @@
 
 #define OSA_ADB_POLICY_VERSION_MASK	0x12345D00
 #define OSA_ADB_POLICY_VERSION_1	0x12345D01
+#define OSA_ADB_POLICY_VERSION_2	0x12345D02
 
 
 

Modified: trunk/src/plugins/kdb/ldap/ldap_exp.c
===================================================================
--- trunk/src/plugins/kdb/ldap/ldap_exp.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/ldap_exp.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -87,6 +87,10 @@
   /* fetch_master_key_list */		       NULL,
   /* store_master_key_list */		       NULL,
   /* Search enc type */                        NULL,
-  /* Change pwd   */                           NULL
+  /* Change pwd   */                           NULL,
+  /* promote_db */                             NULL,
+  /* dbekd_decrypt_key_data */                 NULL,
+  /* dbekd_encrypt_key_data */                 NULL,
+  /* db_invoke */			       krb5_ldap_invoke,
 
 };

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in	2009-10-25 16:55:12 UTC (rev 23038)
@@ -54,8 +54,10 @@
 	$(srcdir)/princ_xdr.c \
 	$(srcdir)/ldap_fetch_mkey.c \
 	$(srcdir)/ldap_service_stash.c \
+	$(srcdir)/kdb_ext.c \
 	$(srcdir)/kdb_xdr.c \
-	$(srcdir)/ldap_err.c
+	$(srcdir)/ldap_err.c \
+	$(srcdir)/lockout.c \
 
 STOBJLISTS=OBJS.ST
 STLIBOBJS= kdb_ldap.o \
@@ -74,8 +76,10 @@
 	princ_xdr.o \
 	ldap_fetch_mkey.o \
 	ldap_service_stash.o \
+	kdb_ext.o \
 	kdb_xdr.o \
-	ldap_err.o
+	ldap_err.o \
+	lockout.o
 
 all-unix:: all-liblinks
 install-unix:: install-libs

Copied: trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c (from rev 23037, users/lhoward/lockout2/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c)

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -162,69 +162,68 @@
 }
 
 
-/* Function to check if a LDAP server supports the SASL external mechanism
- *Return values:
- *   0 => supports
- *   1 => does not support
- *   2 => don't know
+/*
+ * Interrogate the root DSE (zero length DN) for an attribute
+ * value assertion.
  */
-#define ERR_MSG1 "Unable to check if SASL EXTERNAL mechanism is supported by LDAP server. Proceeding anyway ..."
-#define ERR_MSG2 "SASL EXTERNAL mechanism not supported by LDAP server. Can't perform certificate-based bind."
-
-int
-has_sasl_external_mech(context, ldap_server)
+static int
+has_rootdse_ava(context, ldap_server, attribute, value)
     krb5_context     context;
     char             *ldap_server;
+    char             *attribute;
+    char             *value;
 {
     int               i=0, flag=0, ret=0, retval=0;
-    char              *attrs[]={"supportedSASLMechanisms", NULL}, **values=NULL;
+    char              *attrs[2], **values=NULL;
     LDAP              *ld=NULL;
     LDAPMessage       *msg=NULL, *res=NULL;
+    struct berval     cred;
 
+    attrs[0] = attribute;
+    attrs[1] = NULL;
+
     retval = ldap_initialize(&ld, ldap_server);
     if (retval != LDAP_SUCCESS) {
-	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
 	ret = 2; /* Don't know */
 	goto cleanup;
     }
 
+    cred.bv_val = "";
+    cred.bv_len = 0;
+
     /* Anonymous bind */
-    retval = ldap_sasl_bind_s(ld, NULL, NULL, NULL, NULL, NULL, NULL);
+    retval = ldap_sasl_bind_s(ld, "", NULL, &cred, NULL, NULL, NULL);
     if (retval != LDAP_SUCCESS) {
-	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
 	ret = 2; /* Don't know */
 	goto cleanup;
     }
 
     retval = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, NULL, NULL, NULL, 0, &res);
     if (retval != LDAP_SUCCESS) {
-	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
 	ret = 2; /* Don't know */
 	goto cleanup;
     }
 
     msg = ldap_first_message(ld, res);
     if (msg == NULL) {
-	krb5_set_error_message(context, 2, "%s", ERR_MSG1);
 	ret = 2; /* Don't know */
 	goto cleanup;
     }
 
-    values = ldap_get_values(ld, msg, "supportedSASLMechanisms");
+    values = ldap_get_values(ld, msg, attribute);
     if (values == NULL) {
-	krb5_set_error_message(context, 1, "%s", ERR_MSG2);
 	ret = 1; /* Not supported */
 	goto cleanup;
     }
 
     for (i = 0; values[i] != NULL; i++) {
-	if (strcmp(values[i], "EXTERNAL"))
-	    continue;
-	flag = 1;
+	if (strcmp(values[i], value) == 0) {
+	    flag = 1;
+	    break;
+	}
     }
 
     if (flag != 1) {
-	krb5_set_error_message(context, 1, "%s", ERR_MSG2);
 	ret = 1; /* Not supported */
 	goto cleanup;
     }
@@ -243,6 +242,47 @@
     return ret;
 }
 
+#define ERR_MSG1 "Unable to check if SASL EXTERNAL mechanism is supported by LDAP server. Proceeding anyway ..."
+#define ERR_MSG2 "SASL EXTERNAL mechanism not supported by LDAP server. Can't perform certificate-based bind."
+
+/* Function to check if a LDAP server supports the SASL external mechanism
+ *Return values:
+ *   0 => supports
+ *   1 => does not support
+ *   2 => don't know
+ */
+int
+has_sasl_external_mech(context, ldap_server)
+    krb5_context     context;
+    char             *ldap_server;
+{
+    int ret;
+
+    ret = has_rootdse_ava(context, ldap_server,
+			  "supportedSASLMechanisms", "EXTERNAL");
+    switch (ret) {
+    case 1: /* not supported */
+	krb5_set_error_message(context, 1, "%s", ERR_MSG2);
+	break;
+    case 2: /* don't know */
+	krb5_set_error_message(context, 1, "%s", ERR_MSG1);
+	break;
+    default:
+	break;
+    }
+
+    return ret;
+}
+
+int
+has_modify_increment(context, ldap_server)
+    krb5_context     context;
+    char             *ldap_server;
+{
+    return has_rootdse_ava(context, ldap_server,
+			   "supportedFeatures", "1.3.6.1.1.14");
+}
+
 void * krb5_ldap_alloc(krb5_context context, void *ptr, size_t size)
 {
     return realloc(ptr, size);

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -197,6 +197,7 @@
 #ifdef HAVE_EDIRECTORY
     char			*root_certificate_file;
 #endif
+    int				 modify_increment;
     struct _krb5_ldap_server_info *next;
 };
 
@@ -291,6 +292,9 @@
 int
 has_sasl_external_mech(krb5_context, char *);
 
+int
+has_modify_increment(krb5_context, char *);
+
 krb5_error_code
 krb5_ldap_free_server_context_params(krb5_ldap_context *ldap_context);
 
@@ -328,4 +332,23 @@
 ldap_unbind_ext_s(LDAP *, LDAPControl **, LDAPControl **);
 #endif
 
+/* lockout.c */
+krb5_error_code
+krb5_ldap_lockout_check_policy(krb5_context context,
+                               krb5_db_entry *entry,
+                               krb5_timestamp stamp);
+
+krb5_error_code
+krb5_ldap_lockout_audit(krb5_context context,
+                        krb5_db_entry *entry,
+                        krb5_timestamp stamp,
+                        krb5_error_code status);
+
+/* kdb_ext.c */
+krb5_error_code
+krb5_ldap_invoke(krb5_context context,
+                 unsigned int method,
+                 const krb5_data *req,
+                 krb5_data *rep);
+
 #endif

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -229,6 +229,13 @@
 
 	    krb5_clear_error_message(context);
 
+#ifdef LDAP_MOD_INCREMENT
+	    server_info->modify_increment =
+		(has_modify_increment(context, server_info->server_name) == 0);
+#else
+	    server_info->modify_increment = 0;
+#endif /* LDAP_MOD_INCREMENT */
+
 	    for (conns=0; conns < ldap_context->max_server_conns; ++conns) {
 		if ((st=krb5_ldap_initialize(ldap_context, server_info)) != 0)
 		    break;

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif	2009-10-25 16:55:12 UTC (rev 23038)
@@ -337,6 +337,42 @@
                 SINGLE-VALUE)
 
 
+##### Number of consecutive pre-authentication failures before lockout
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 1.3.6.1.4.1.5322.21.2.1
+                NAME 'krbPwdMaxFailure' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Period after which bad preauthentication count will be reset
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 1.3.6.1.4.1.5322.21.2.2
+                NAME 'krbPwdFailureCountInterval' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Period in which lockout is enforced
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 1.3.6.1.4.1.5322.21.2.3
+                NAME 'krbPwdLockoutDuration' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
 ##### FDN pointing to a Kerberos Password Policy object
 
 dn: cn=schema
@@ -760,7 +796,7 @@
                 NAME 'krbPwdPolicy' 
                 SUP top
                 MUST ( cn )
-                MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength ) )
+                MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdMaxFailure $ krbPwdFailureCountInterval $ krbPwdLockoutDuration ) )
 
 
 ##### The krbTicketPolicyAux holds Kerberos ticket policy attributes.

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema	2009-10-25 16:55:12 UTC (rev 23038)
@@ -270,6 +270,33 @@
                 SINGLE-VALUE)
 
 
+##### Number of consecutive pre-authentication failures before lockout
+
+attributetype ( 1.3.6.1.4.1.5322.21.2.1
+                NAME 'krbPwdMaxFailure' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Period after which bad preauthentication count will be reset
+
+attributetype ( 1.3.6.1.4.1.5322.21.2.2
+                NAME 'krbPwdFailureCountInterval' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
+##### Period in which lockout is enforced
+
+attributetype ( 1.3.6.1.4.1.5322.21.2.3
+                NAME 'krbPwdLockoutDuration' 
+                EQUALITY integerMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+                SINGLE-VALUE)
+
+
 ##### FDN pointing to a Kerberos Password Policy object
 
 attributetype ( 2.16.840.1.113719.1.301.4.36.1
@@ -506,7 +533,6 @@
                 EQUALITY distinguishedNameMatch
                 SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
 
-
 ########################################################################
 ########################################################################
 # 		        Object Class Definitions                       #
@@ -616,7 +642,7 @@
                 NAME 'krbPwdPolicy' 
                 SUP top
                 MUST ( cn )
-                MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength ) )
+                MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdMaxFailure $ krbPwdFailureCountInterval $ krbPwdLockoutDuration ) )
 
 
 ##### The krbTicketPolicyAux holds Kerberos ticket policy attributes.

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h	2009-10-25 16:55:12 UTC (rev 23038)
@@ -81,6 +81,15 @@
 #define KDB_LAST_SUCCESS_ATTR                0x000800
 #define KDB_LAST_FAILED_ATTR                 0x001000
 #define KDB_FAIL_AUTH_COUNT_ATTR             0x002000
+#define KDB_LOCKED_TIME_ATTR                 0x004000
+
+/*
+ * This is a private contract between krb5_ldap_lockout_audit()
+ * and krb5_ldap_put_principal(). If present, it means that the
+ * krbPwdMaxFailure attribute should be incremented by one.
+ */
+#define KADM5_FAIL_AUTH_COUNT_INCREMENT	     0x080000 /* KADM5_CPW_FUNCTION */
+
 extern struct timeval timeout;
 extern char *policyclass[];
 

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -863,7 +863,7 @@
 	    establish_links = TRUE;
 	}
 
-	if ((entries->last_success)!=0) {
+	if (entries->mask & KADM5_LAST_SUCCESS) {
 	    memset(strval, 0, sizeof(strval));
 	    if ((strval[0]=getstringtime(entries->last_success)) == NULL)
 		goto cleanup;
@@ -874,7 +874,7 @@
 	    free (strval[0]);
 	}
 
-	if (entries->last_failed!=0) {
+	if (entries->mask & KADM5_LAST_FAILED) {
 	    memset(strval, 0, sizeof(strval));
 	    if ((strval[0]=getstringtime(entries->last_failed)) == NULL)
 		goto cleanup;
@@ -885,9 +885,58 @@
 	    free(strval[0]);
 	}
 
-	if (entries->fail_auth_count!=0) {
-	    if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", LDAP_MOD_REPLACE, entries->fail_auth_count)) !=0)
+	if (entries->mask & KADM5_FAIL_AUTH_COUNT) {
+	    krb5_kvno fail_auth_count;
+
+	    fail_auth_count = entries->fail_auth_count;
+	    if (entries->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT)
+		fail_auth_count++;
+
+	    st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
+					   LDAP_MOD_REPLACE,
+					   fail_auth_count);
+	    if (st != 0)
 		goto cleanup;
+	} else if (entries->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) {
+	    /*
+	     * If the client library and server supports RFC 4525,
+	     * then use it to increment by one the value of the
+	     * krbLoginFailedCount attribute. Otherwise, assert the
+	     * (provided) old value by deleting it before adding.
+	     */
+#ifdef LDAP_MOD_INCREMENT
+	    if (ldap_server_handle->server_info->modify_increment) {
+		st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
+					       LDAP_MOD_INCREMENT, 1);
+		if (st != 0)
+		    goto cleanup;
+	    } else
+#endif /* LDAP_MOD_INCREMENT */
+	    if (entries->fail_auth_count == 0) {
+		/*
+		 * Unfortunately we have no way of distinguishing between
+		 * an absent and a zero-valued attribute by the time we are
+		 * called here. So, although this creates a race condition,
+		 * it appears impossible to assert the old value as that
+		 * would fail were the attribute absent.
+		 */
+		st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
+					       LDAP_MOD_REPLACE, 1);
+		if (st != 0)
+		    goto cleanup;
+	    } else {
+		st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
+					       LDAP_MOD_DELETE,
+					       entries->fail_auth_count);
+		if (st != 0)
+		    goto cleanup;
+
+		st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
+					       LDAP_MOD_ADD,
+					       entries->fail_auth_count + 1);
+		if (st != 0)
+		    goto cleanup;
+	    }
 	}
 
 	if (entries->mask & KADM5_MAX_LIFE) {
@@ -1180,6 +1229,9 @@
 		krb5_set_error_message(context, st, "%s", errbuf);
 		goto cleanup;
 	    }
+
+	    if (entries->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT)
+		entries->fail_auth_count++;
 	}
     }
 

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -39,7 +39,9 @@
 
 static char *password_policy_attributes[] = { "cn", "krbmaxpwdlife", "krbminpwdlife",
 					      "krbpwdmindiffchars", "krbpwdminlength",
-					      "krbpwdhistorylength", NULL };
+					      "krbpwdhistorylength", "krbpwdmaxfailure",
+					      "krbpwdfailurecountinterval",
+					      "krbpwdlockoutduration", NULL };
 
 /*
  * Function to create password policy object.
@@ -97,7 +99,13 @@
 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_ADD,
 					  (signed) policy->pw_min_length)) != 0)
 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_ADD,
-					  (signed) policy->pw_history_num)) != 0))
+					  (signed) policy->pw_history_num)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmaxfailure", LDAP_MOD_ADD,
+					  (signed) policy->pw_max_fail)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdfailurecountinterval", LDAP_MOD_ADD,
+					  (signed) policy->pw_failcnt_interval)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdlockoutduration", LDAP_MOD_ADD,
+					  (signed) policy->pw_lockout_duration)) != 0))
 	goto cleanup;
 
     /* password policy object creation */
@@ -157,7 +165,13 @@
 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_REPLACE,
 					  (signed) policy->pw_min_length)) != 0)
 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_REPLACE,
-					  (signed) policy->pw_history_num)) != 0))
+					  (signed) policy->pw_history_num)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmaxfailure", LDAP_MOD_REPLACE,
+					  (signed) policy->pw_max_fail)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdfailurecountinterval", LDAP_MOD_REPLACE,
+					  (signed) policy->pw_failcnt_interval)) != 0)
+	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdlockoutduration", LDAP_MOD_REPLACE,
+					  (signed) policy->pw_lockout_duration)) != 0))
 	goto cleanup;
 
     /* modify the password policy object. */
@@ -199,6 +213,10 @@
     krb5_ldap_get_value(ld, ent, "krbpwdminlength", &(pol_entry->pw_min_length));
     krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &(pol_entry->pw_history_num));
 
+    krb5_ldap_get_value(ld, ent, "krbpwdmaxfailure", &(pol_entry->pw_max_fail));
+    krb5_ldap_get_value(ld, ent, "krbpwdfailurecountinterval", &(pol_entry->pw_failcnt_interval));
+    krb5_ldap_get_value(ld, ent, "krbpwdlockoutduration", &(pol_entry->pw_lockout_duration));
+
     /* Get the reference count */
     pol_dn = ldap_get_dn(ld, ent);
     st = krb5_ldap_get_reference_count (context, pol_dn, "krbPwdPolicyReference",

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -87,6 +87,9 @@
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"6#subtree#","#krbPwdMaxFailure"},
+    {"6#subtree#","#krbPwdFailureCountInterval"},
+    {"6#subtree#","#krbPwdLockoutDuration"},
     { "","" }
 };
 
@@ -116,6 +119,9 @@
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"2#subtree#","#krbPwdMaxFailure"},
+    {"2#subtree#","#krbPwdFailureCountInterval"},
+    {"2#subtree#","#krbPwdLockoutDuration"},
     { "", "" }
 };
 
@@ -187,6 +193,9 @@
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"6#subtree#","#krbPwdMaxFailure"},
+    {"6#subtree#","#krbPwdFailureCountInterval"},
+    {"6#subtree#","#krbPwdLockoutDuration"},
     { "","" }
 };
 
@@ -225,6 +234,9 @@
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"2#subtree#","#krbPwdMaxFailure"},
+    {"2#subtree#","#krbPwdFailureCountInterval"},
+    {"2#subtree#","#krbPwdLockoutDuration"},
     { "", "" }
 };
 

Modified: trunk/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
===================================================================
--- trunk/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports	2009-10-25 16:55:12 UTC (rev 23038)
@@ -51,3 +51,4 @@
 krb5_ldap_create
 krb5_ldap_set_mkey_list
 krb5_ldap_get_mkey_list
+krb5_ldap_invoke

Copied: trunk/src/plugins/kdb/ldap/libkdb_ldap/lockout.c (from rev 23037, users/lhoward/lockout2/src/plugins/kdb/ldap/libkdb_ldap/lockout.c)

Modified: trunk/src/slave/kpropd.c
===================================================================
--- trunk/src/slave/kpropd.c	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/slave/kpropd.c	2009-10-25 16:55:12 UTC (rev 23038)
@@ -190,7 +190,7 @@
 
 static kadm5_ret_t
 kadm5_get_kiprop_host_srv_name(krb5_context context,
-			       const char *realm,
+			       const char *realm_name,
 			       char **host_service_name);
 
 static void usage()
@@ -587,6 +587,36 @@
 	exit(0);
 }
 
+/* Default timeout can be changed using clnt_control() */
+static struct timeval full_resync_timeout = { 25, 0 };
+
+static kdb_fullresync_result_t *
+full_resync(CLIENT *clnt)
+{
+	static kdb_fullresync_result_t clnt_res;
+	uint32_t vers = IPROPX_VERSION_1; /* max version we support */
+	enum clnt_stat status;
+
+	memset(&clnt_res, 0, sizeof(clnt_res));
+
+	status = clnt_call (clnt, IPROP_FULL_RESYNC_EXT,
+			    (xdrproc_t) xdr_u_int32,
+			    (caddr_t) &vers,
+			    (xdrproc_t) xdr_kdb_fullresync_result_t,
+			    (caddr_t) &clnt_res,
+			    full_resync_timeout);
+	if (status == RPC_PROCUNAVAIL) {
+		status = clnt_call (clnt, IPROP_FULL_RESYNC,
+				    (xdrproc_t) xdr_void,
+				    (caddr_t *)&vers,
+		      		    (xdrproc_t) xdr_kdb_fullresync_result_t,
+				    (caddr_t) &clnt_res,
+				    full_resync_timeout);
+	}
+
+	return (status == RPC_SUCCESS) ? &clnt_res : NULL;
+}
+
 /*
  * Routine to handle incremental update transfer(s) from master KDC
  */
@@ -609,7 +639,6 @@
 	static kdb_last_t mylast;
 
 	kdb_fullresync_result_t *full_ret;
-	char *full_resync_arg = NULL;
 
 	kadm5_iprop_handle_t handle;
 	kdb_hlog_t *ulog;
@@ -701,7 +730,7 @@
 				      master_svc_princstr,
 				      &params,
 				      KADM5_STRUCT_VERSION,
-				      KADM5_API_VERSION_2,
+				      KADM5_API_VERSION_3,
 				      db_args,
 				      &server_handle);
 
@@ -788,10 +817,7 @@
 						== 0)) {
 				break;
 			} else {
-
-				full_ret = iprop_full_resync_1((void *)
-						&full_resync_arg, handle->clnt);
-
+				full_ret = full_resync(handle->clnt);
 				if (full_ret == (kdb_fullresync_result_t *)
 							NULL) {
 					clnt_perror(handle->clnt,
@@ -873,8 +899,8 @@
 					     db_args);
 
 			if (retval) {
-			    char *msg = krb5_get_error_message(kpropd_context,
-							       retval);
+			    const char *msg =
+				krb5_get_error_message(kpropd_context, retval);
 			    syslog(LOG_ERR,
 				   _("kpropd: ulog_replay failed (%s), updates not registered."), msg);
 			    krb5_free_error_message(kpropd_context, msg);
@@ -1633,8 +1659,10 @@
 			dup(0);
 		}
 
-		execv(kdb_util, edit_av);
-		retval = errno;
+		if (execv(kdb_util, edit_av) < 0)
+			retval = errno;
+		else
+			retval = 0;
 		if (!debug)
 			dup2(save_stderr, 2);
 		com_err(progname, retval, "while trying to exec %s",
@@ -1667,7 +1695,7 @@
  */
 static kadm5_ret_t
 kadm5_get_kiprop_host_srv_name(krb5_context context,
-			       const char *realm,
+			       const char *realm_name,
 			       char **host_service_name)
 {
 	char *name;

Modified: trunk/src/slave/kslave_update
===================================================================
--- trunk/src/slave/kslave_update	2009-10-25 14:03:55 UTC (rev 23037)
+++ trunk/src/slave/kslave_update	2009-10-25 16:55:12 UTC (rev 23038)
@@ -23,7 +23,7 @@
 then
 
 	date
-	$KDB5_EDIT dump $DUMPFILE > /dev/null
+	$KDB5_UTIL dump $DUMPFILE > /dev/null
 
 	$KPROP -d -f $DUMPFILE ${SLAVE}
 	rm $DUMPFILE




More information about the cvs-krb5 mailing list