Account lockout
authorGreg Hudson <ghudson@mit.edu>
Sun, 25 Oct 2009 16:55:12 +0000 (16:55 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sun, 25 Oct 2009 16:55:12 +0000 (16:55 +0000)
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.

ticket: 6577

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23038 dc483132-0cff-0310-8789-dd5450dbe970

79 files changed:
src/include/iprop.h
src/include/iprop_hdr.h
src/include/kdb.h
src/kadmin/cli/kadmin.c
src/kadmin/dbutil/dump.c
src/kadmin/dbutil/kadm5_create.c
src/kadmin/dbutil/kdb5_util.M
src/kadmin/dbutil/kdb5_util.c
src/kadmin/server/ipropd_svc.c
src/kadmin/server/ovsec_kadmd.c
src/kadmin/server/server_stubs.c
src/kadmin/testing/scripts/init_db
src/kadmin/testing/scripts/start_servers_local
src/kadmin/testing/tcl/util.t
src/kadmin/testing/util/tcl_kadm5.c
src/kdc/do_as_req.c
src/kdc/extern.c
src/kdc/main.c
src/lib/kadm5/admin.h
src/lib/kadm5/admin_internal.h
src/lib/kadm5/clnt/client_init.c
src/lib/kadm5/kadm_rpc_xdr.c
src/lib/kadm5/server_internal.h
src/lib/kadm5/srv/server_init.c
src/lib/kadm5/srv/server_kdb.c
src/lib/kadm5/srv/svr_policy.c
src/lib/kadm5/srv/svr_principal.c
src/lib/kadm5/unit-test/api.2/mod-principal-v2.exp
src/lib/kadm5/unit-test/api.3/chpass-principal-v2.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/chpass-principal.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/crte-policy.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/crte-principal.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/destroy.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/dlte-policy.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/dlte-principal.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/get-policy.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/get-principal-v2.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/get-principal.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/init-v2.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/init.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/mod-policy.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/mod-principal-v2.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/mod-principal.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/randkey-principal-v2.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/api.3/randkey-principal.exp [new file with mode: 0644]
src/lib/kadm5/unit-test/config/unix.exp
src/lib/kadm5/unit-test/destroy-test.c
src/lib/kadm5/unit-test/handle-test.c
src/lib/kadm5/unit-test/init-test.c
src/lib/kadm5/unit-test/iter-test.c
src/lib/kadm5/unit-test/lib/lib.t
src/lib/kadm5/unit-test/randkey-test.c
src/lib/kadm5/unit-test/setkey-test.c
src/lib/kdb/iprop.x
src/lib/kdb/kdb_convert.c
src/plugins/kdb/db2/Makefile.in
src/plugins/kdb/db2/db2_exp.c
src/plugins/kdb/db2/kdb_db2.c
src/plugins/kdb/db2/kdb_db2.h
src/plugins/kdb/db2/kdb_ext.c [new file with mode: 0644]
src/plugins/kdb/db2/lockout.c [new file with mode: 0644]
src/plugins/kdb/db2/pol_xdr.c
src/plugins/kdb/db2/policy_db.h
src/plugins/kdb/ldap/ldap_exp.c
src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c [new file with mode: 0644]
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h
src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c
src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c
src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
src/plugins/kdb/ldap/libkdb_ldap/lockout.c [new file with mode: 0644]
src/slave/kpropd.c
src/slave/kslave_update

index 208f4dce0a0c853b2dc2df6dffedbca0da5a3a60..9cfbb309369a02d1ea201e4f5a4d1f40433de7a8 100644 (file)
@@ -205,6 +205,9 @@ extern  kdb_incr_result_t * iprop_get_updates_1_svc(kdb_last_t *, struct svc_req
 #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 @@ extern  kdb_incr_result_t * iprop_get_updates_1_svc();
 #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 */
 
index d629542bbb1a877d5d694d3c859a1dbdb8f2e83e..cd6d3b440bd0758d202a45e16f7b7c27aabfacf9 100644 (file)
@@ -35,6 +35,13 @@ enum iprop_role {
 };
 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
index 8c0cd247a2991f73fc84ff850830d98e65889550..d74e3e3235a12ffeabab641ae6ec9204af901e86 100644 (file)
@@ -169,6 +169,10 @@ typedef struct _osa_policy_ent_t {
     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 @@ typedef struct __krb5_key_salt_tuple {
 
 #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_dbe_update_mod_princ_data( krb5_context          context,
                                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 @@ typedef struct _kdb_vftabl {
                   const krb5_data *req,
                   krb5_data *rep );
 } kdb_vftabl;
+
 #endif /* !defined(_WIN32) */
 
 #endif /* KRB5_KDB5__ */
index ad9f6bc9bdab40a523dd74de4e168bbacb79348c..51746def446f2f8714be10a28381f7a21a16eeea 100644 (file)
@@ -486,7 +486,7 @@ kadmin_startup(int argc, char *argv[])
                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 @@ kadmin_startup(int argc, char *argv[])
                    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 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc,
             }
         }
 #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 @@ kadmin_modprinc_usage()
 {
     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 @@ kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy,
                 *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 @@ kadmin_addmodpol_usage(char *func)
 {
     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 @@ kadmin_getpol(int argc, char *argv[])
                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);
 }
index 8dab4605cef775bb95e9847698a0f89f7b94e9cb..c03e88d1230efabcc3a93b7eb437d55d7073e7d9 100644 (file)
@@ -66,13 +66,17 @@ static int  recursive;
 #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_k5beta7_princ_withpolicy
 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 @@ static int process_k5beta6_record (char *, krb5_context,
                                   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_version r1_3_version = {
      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 @@ static const char null_mprinc_name[] = "kdb5_dump@MISSING";
 #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 verboseoption[] = "-verbose";
 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 @@ dump_k5beta_iterator(ptr, entry)
                (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 @@ dump_k5beta_iterator(ptr, entry)
        }
        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 @@ dump_k5beta6_iterator_ext(ptr, entry, kadm)
                    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 @@ dump_k5beta6_iterator_ext(ptr, entry, kadm)
            /* Print trailer */
            fprintf(arg->ofile, ";\n");
 
-           if (arg->verbose)
+           if (arg->flags & FLAG_VERBOSE)
                fprintf(stderr, "%s\n", name);
        }
        else {
@@ -926,6 +956,19 @@ void dump_k5beta7_policy(void *data, osa_policy_ent_t entry)
             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 void print_key_data(FILE *f, krb5_key_data *key_data)
 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 @@ static krb5_error_code dump_ov_princ(krb5_pointer ptr, krb5_db_entry *kdb)
         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 @@ static krb5_error_code dump_ov_princ(krb5_pointer ptr, krb5_db_entry *kdb)
 
 /*
  * 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 @@ dump_db(argc, argv)
     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_db(argc, argv)
             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 @@ dump_db(argc, argv)
                 * 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 @@ dump_db(argc, argv)
                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 @@ update_tl_data(kcontext, dbentp, mod_name, mod_date, last_pwd_change)
  * 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 @@ process_k5beta_record(fname, kcontext, filep, verbose, linenop)
                                error++;
                            }
                            else {
-                               if (verbose)
+                               if (flags & FLAG_VERBOSE)
                                    fprintf(stderr, add_princ_fmt, name);
                                retval = 0;
                            }
@@ -1773,11 +1829,11 @@ process_k5beta_record(fname, kcontext, filep, verbose, linenop)
  * 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 @@ process_k5beta6_record(fname, kcontext, filep, verbose, linenop)
                                name, error_message(kret));
                    }
                    else {
-                       if (verbose)
+                       if (flags & FLAG_VERBOSE)
                            fprintf(stderr, add_princ_fmt, name);
                        retval = 0;
                    }
@@ -2061,17 +2117,19 @@ process_k5beta6_record(fname, kcontext, filep, verbose, linenop)
 }
 
 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 @@ process_k5beta7_policy(fname, kcontext, filep, verbose, linenop)
              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 @@ process_k5beta7_record(fname, kcontext, filep, verbose, linenop)
      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 @@ process_k5beta7_record(fname, kcontext, filep, verbose, linenop)
  * 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 @@ process_ov_record(fname, kcontext, filep, verbose, linenop)
      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;
@@ -2175,16 +2283,52 @@ process_ov_record(fname, kcontext, filep, verbose, linenop)
      return 0;
 }
 
+/*
+ * 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 @@ restore_dump(programname, kcontext, dumpfile, f, verbose, dump)
     while (!(error = (*dump->load_record)(dumpfile,
                                          kcontext, 
                                          f,
-                                         verbose,
+                                         flags,
                                          &lineno)))
         ;
     if (error != -1)
@@ -2211,8 +2355,8 @@ restore_dump(programname, kcontext, dumpfile, f, verbose, dump)
 }
 
 /*
- * 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 @@ load_db(argc, argv)
     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 @@ load_db(argc, argv)
     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_db(argc, argv)
             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 @@ load_db(argc, argv)
                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 @@ load_db(argc, argv)
     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_db(argc, argv)
              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 @@ load_db(argc, argv)
              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 @@ load_db(argc, argv)
      * 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 @@ load_db(argc, argv)
             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 @@ load_db(argc, argv)
      * 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 @@ load_db(argc, argv)
         *      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 @@ load_db(argc, argv)
            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 @@ load_db(argc, argv)
     }
 
     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 @@ load_db(argc, argv)
 
     /* 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 @@ error:
      *
      * 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);
              /* 
index c2196e54b43821587691c5d24385335be90ee0a9..a232babd168b4c831ed227ca3c81a4cd460b3504 100644 (file)
@@ -108,7 +108,7 @@ int kadm5_create_magic_princs(kadm5_config_params *params,
          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");
index f566781ebd6a8f2948e60850a92d0ef3918ec5b9..33ab01aa18efcc16cb18625200f89cf0aedd6b8f 100644 (file)
@@ -99,14 +99,14 @@ Stores the master principal's keys in a stash file.  The
 .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 @@ causes the dump to be in
 .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 probably retrieve more principals than the \fB\-rev\fP
 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.
index 1b0d5a492ede8ab6acbf152d84bfafe588ca5fb7..a4b2e686d0703f0e006742e7fb96182c6aca3d6f 100644 (file)
@@ -90,10 +90,10 @@ void usage()
             "\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"
index 9140bbdc4c37be52b5ccaa0780e6611cd9f99103..127a5045d2527dbebed576c7bdfb835950cc14c7 100644 (file)
@@ -241,8 +241,8 @@ getclhoststr(char *clprinc, char *cl, size_t len)
     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 @@ iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp)
     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 @@ iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp)
 
     /*
      * 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 @@ out:
     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 @@ krb5_iprop_prog_1(struct svc_req *rqstp,
        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)"),
index fb42c7bde2bfc6a20e9581a2c7b2539f8c056bdc..c01cbef73a62d5d77615a8996e92fdadc12f91c5 100644 (file)
@@ -306,7 +306,7 @@ int main(int argc, char *argv[])
      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);
index dc949ff18bdceedcf61811c01d834097bb19f9be..9449fe8c2249c4f8707e15f479e3a1e8e6f96969 100644 (file)
@@ -1598,12 +1598,14 @@ generic_ret *init_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
      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);
index 1cb96f843c6f75c1b4f47b73f708c90bd7d0ca9a..d5930223da3714ead0a8f8140325763dd1eedb6c 100755 (executable)
@@ -103,13 +103,13 @@ if {[info exists env(USER)]} {
 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}}
index 8cd0f3a61dd5d9c9ba1cca122af7dd9d7150d92e..a8890d7318e52b9e2d3db717be380d532ec7e06a 100755 (executable)
@@ -83,7 +83,7 @@ if { [catch {
        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]
index 0e39061f7763e1d726b0ed7b91de55055262f87d..7721609902392c6690f83e3f2e0dbbc0eee89410 100644 (file)
@@ -7,7 +7,7 @@ proc princ_w_pol {name policy} {
 }
 
 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} {
index 6679ce0a7c5e8b46e9e010e71831c23657d20b55..08f3a52a4d7f52ec516cbb0e67f0e315129b1f78 100644 (file)
@@ -71,7 +71,10 @@ static struct flagval policy_mask_flags[] = {
      {"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 @@ static int parse_principal_ent(Tcl_Interp *interp, char *list,
          retcode = TCL_ERROR;
          goto finished;
      }
+     princ->n_tl_data = tmp;
 
 finished:
      Tcl_Free((char *) argv);
@@ -1360,6 +1364,15 @@ static Tcl_DString *unparse_policy_ent(kadm5_policy_ent_t policy)
      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 @@ static int parse_policy_ent(Tcl_Interp *interp, char *list,
          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 @@ static int parse_policy_ent(Tcl_Interp *interp, char *list,
      }
      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 @@ void Tcl_kadm5_init(Tcl_Interp *interp)
      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);
index 304b76b4d2cbdbee2f610df1ef7068be7041c15d..737def8d2a03ed76ebc7c30fb37dbb171b737782 100644 (file)
@@ -106,7 +106,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     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 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
            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 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
     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 @@ egress:
        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 @@ egress:
            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)
index 3427bcfff7c8ddb688d760e355e839675bb28654..7ebc7bb3a64e5f70c1297a1fab63877176eeaef4 100644 (file)
@@ -38,11 +38,6 @@ krb5_data empty_string = {0, 0, ""};
 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 */
index 83c7de61ee8a1b7caf6ea05a65a5030847972708..9ce3f48941966a101d2456967cbd4d7ae7e6ca26 100644 (file)
@@ -381,10 +381,7 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname,
     }
 
     /* 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);
index 9c98a0669cc14e1b23ac24fa1db8a4660e311cf8..5105c5e457d27e878887fd66e1711ee5d1853033 100644 (file)
@@ -112,8 +112,8 @@ typedef long                kadm5_ret_t;
 #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 @@ typedef long                kadm5_ret_t;
 #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 @@ typedef long                kadm5_ret_t;
 
 #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 @@ typedef struct _kadm5_policy_ent_t {
        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;
 
 /*
index 69e7bd6bcbb5c87f91a1bee00aaabdac1374735b..f08325c8b424c603b2f2097cb694face5fc58141 100644 (file)
@@ -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; \
 }
 
index cc48a8c7462e37cb44ac1e2555d81a84b65819aa..0b817b8bceb15bc10c28e79686151a085818af88 100644 (file)
@@ -205,7 +205,7 @@ static kadm5_ret_t _kadm5_init_any(krb5_context context, char *client_name,
      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 @@ static kadm5_ret_t _kadm5_init_any(krb5_context context, char *client_name,
 #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;
index c357dbf6e854940f4f9140f0f59283781464d306..8ddf33a2477d192942ec7a5abfaf09e215b9f3fa 100644 (file)
@@ -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 @@ xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp)
 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_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
                       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 @@ xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp)
        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 @@ xdr_cprinc3_arg(XDR *xdrs, cprinc3_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)) {
@@ -563,7 +587,8 @@ xdr_mprinc_arg(XDR *xdrs, mprinc_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)) {
@@ -799,7 +824,8 @@ xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp)
                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 @@ xdr_cpol_arg(XDR *xdrs, cpol_arg *objp)
        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 @@ xdr_mpol_arg(XDR *xdrs, mpol_arg *objp)
        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 @@ xdr_gpol_ret(XDR *xdrs, gpol_ret *objp)
                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);
        }
 
index 4e890e8aa93fb759bbf22e28db124771ce640c05..c9bb073d36959658f8963357a642c5d5f1ced344 100644 (file)
@@ -111,12 +111,13 @@ extern    krb5_principal  current_caller;
   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) \
 { \
index 47bc22c4d6f6642df1642bb868749902ed5e319a..d5426f81019b323121dc10ae38f27a6ad53b9491 100644 (file)
@@ -273,7 +273,7 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
         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;
 
index 47f00c0713761dbd95cd96b1917a04faa57e5dcb..fe2020db1d199d1dfd4378123285e30b3e89d61a 100644 (file)
@@ -395,6 +395,9 @@ kdb_put_entry(kadm5_server_handle_t handle,
 
     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);
index 5b7828c1bdc64fae060c704887f4dea4fa059ada..0d8c5ced631b3487c15acbb7d1afb75453cc56df 100644 (file)
@@ -140,6 +140,26 @@ kadm5_create_policy_internal(void *server_handle,
        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 @@ kadm5_modify_policy_internal(void *server_handle,
     }
     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 @@ kadm5_get_policy(void *server_handle, kadm5_policy_t name,
     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;
index 1a60f52f4a00ef75f8a0965896aa2b99c882b0a1..7ba89ecd5844b6245a8772d87418cd9d81517d6f 100644 (file)
@@ -650,8 +650,6 @@ kadm5_modify_principal(void *server_handle,
         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 @@ kadm5_modify_principal(void *server_handle,
         }
     }
 
+    /*
+     * 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 @@ kadm5_chpass_principal_3(void *server_handle,
     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 @@ kadm5_randkey_principal_3(void *server_handle,
     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 @@ kadm5_randkey_principal_3(void *server_handle,
     }
 
     /* 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 @@ kadm5_setv4key_principal(void *server_handle,
     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 @@ kadm5_setkey_principal_3(void *server_handle,
     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;
 
index 44c835e578ee14f04316eb4428ac0d339e8851bf..9d654103047c08dcbca36a5707ae2bf59d918d40 100644 (file)
@@ -42,11 +42,12 @@ proc test100_104 {} {
                {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 {
diff --git a/src/lib/kadm5/unit-test/api.3/chpass-principal-v2.exp b/src/lib/kadm5/unit-test/api.3/chpass-principal-v2.exp
new file mode 100644 (file)
index 0000000..8361fb0
--- /dev/null
@@ -0,0 +1,68 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "chpass-principal 200"
+proc test200 {} {
+    global test prompt
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal "$test/a"]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+
+    # I'd like to specify a long list of keysalt tuples and make sure
+    # that chpass does the right thing, but we can only use those
+    # enctypes that krbtgt has a key for: des-cbc-crc:normal and
+    # des-cbc-crc:v4, according to the prototype kdc.conf.
+    if {! [cmd [format {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_chpass_principal $server_handle "%s/a" newpassword
+    } $test]]} {
+       perror "$test: unexpected failure in chpass_principal"
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle  "%s/a" p \
+               {KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+    } $test]]} {
+       perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 16\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting num_keys"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting num_keys"
+           return
+       }
+    }
+
+    # XXX Perhaps I should actually check the key type returned.
+    if {$num_keys == 3} {
+       pass "$test"
+    } else {
+       fail "$test: $num_keys keys, should be 3"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test200
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/chpass-principal.exp b/src/lib/kadm5/unit-test/api.3/chpass-principal.exp
new file mode 100644 (file)
index 0000000..53a96e5
--- /dev/null
@@ -0,0 +1,176 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "chpass-principal 180"
+proc test180 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_chpass_principal $server_handle "%s/a" FoobarBax
+    } $test]
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test180 }
+
+test "chpass-principal 180.5"
+proc test1805 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_chpass_principal $server_handle "%s/a" FoobarBax
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test1805 }
+
+#
+# admin with changepw service tickets try to change other principals
+# password, failes with AUTH error
+test "chpass-principal 180.625"
+proc test180625 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_chpass_principal $server_handle "%s/a" password
+    } $test] "AUTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test180625 }
+
+test "chpass-principal 180.75"
+proc test18075 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_chpass_principal $server_handle "%s/a" Foobar
+    } $test] "AUTH_CHANGEPW"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test18075 }
+
+test "chpass-principal 182"
+proc test182 {} {
+    global test
+
+    if { ! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_chpass_principal $server_handle kadmin/history password
+    } "PROTECT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test182
+
+test "chpass-principal 183"
+proc test183 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if { ! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_chpass_principal null "%s/a" password
+    } $test] "BAD_SERVER_HANDLE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test183
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/crte-policy.exp b/src/lib/kadm5/unit-test/api.3/crte-policy.exp
new file mode 100644 (file)
index 0000000..017bc31
--- /dev/null
@@ -0,0 +1,956 @@
+load_lib lib.t
+api_exit
+api_start
+
+# Description: (1) Fails for mask with undefined bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 1"
+proc test1 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               0xF01000
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test1
+
+# Description: (2) Fails if caller connected with CHANGEPW_SERVICE.
+test "create-policy 2"
+proc test2 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy";
+       return
+    }
+}
+if {$RPC} { test2 }
+
+# Description: (3) Fails for mask without POLICY bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 3"
+proc test3 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               0x000000
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test3
+
+# Description: (4) Fails for mask with REF_COUNT bit set.
+test "create-policy 4"
+proc test4 {} {
+    global test
+    
+    if {! (( ! [policy_exists "$test/a"]) ||
+           [delete_policy "$test/a"])} {
+            error_and_restart "$test: couldn't delete policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY KADM5_REF_COUNT}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test4
+
+# Description: (5) Fails for invalid policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 5"
+proc test5 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/\a"] \
+               {KADM5_POLICY}
+    } $test] "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test5
+
+# Description: (6) Fails for existing policy name.
+test "create-policy 6"
+proc test6 {} {
+    global test
+#    set prms_id 777
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_create_policy $server_handle [simple_policy test-pol] \
+               {KADM5_POLICY}
+    } "DUP"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test6
+
+# Description: (7) Fails for null policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 7"
+proc test7 {} {
+    global test
+#    set prms_id 1977
+#    setup_xfail {*-*-*} $prms_id
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_create_policy $server_handle [simple_policy null] \
+               {KADM5_POLICY}
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test7
+
+# Description: (8) Fails for empty-string policy name.
+test "create-policy 8"
+proc test8 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_create_policy $server_handle [simple_policy ""] \
+               {KADM5_POLICY}
+    } "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test8
+
+# Description: (9) Accepts 0 for pw_min_life.
+test "create-policy 9"
+proc test9 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY KADM5_PW_MIN_LIFE}
+    } $test]]} {
+       fail "$test: create failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test9
+
+# Description: (10) Accepts non-zero for pw_min_life.
+test "create-policy 10"
+proc test10 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_create_policy $server_handle {"%s/a" 32 0 0 0 0 0 } \
+               {KADM5_POLICY KADM5_PW_MIN_LIFE}
+    } $test]]} {
+       fail "$test"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retreuve policy"
+       return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+       -re "32\n$prompt$"              { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test10
+
+# Description: (11) Accepts 0 for pw_max_life.
+test "create-policy 11"
+proc test11 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY KADM5_PW_MAX_LIFE}
+    } $test]]} {
+       fail "$test"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retreuve policy"
+       return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test11
+
+# Description: (12) Accepts non-zero for pw_max_life.
+test "create-policy 12"
+proc test12 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_policy $server_handle {"%s/a" 0 32 0 0 0 0 } \
+               {KADM5_POLICY KADM5_PW_MAX_LIFE}
+    } $test]]} {
+       fail "$test"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retreuve policy"
+       return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+       -re "32\n$prompt$"              { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test12
+
+# Description: (13) Rejects 0 for pw_min_length.
+test "create-policy 13"
+proc test13 {} {
+    global test
+    global prompt
+
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY KADM5_PW_MIN_LENGTH}
+    } $test] "BAD_LENGTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test13
+
+# Description: (14) Accepts non-zero for pw_min_length.
+test "create-policy 14"
+proc test14 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_policy $server_handle {"%s/a" 0 0 8 0 0 0 } \
+               {KADM5_POLICY KADM5_PW_MIN_LENGTH}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retreuve policy"
+       return
+    }
+    send "lindex \$policy 3\n"
+    expect {
+       -re "8\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test14
+
+# Description: (15) Rejects 0 for pw_min_classes.
+test "create-policy 15"
+proc test15 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test15
+
+# Description: (16) Accepts 1 for pw_min_classes.
+test "create-policy 16"
+proc test16 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_policy $server_handle {"%s/a" 0 0 0 1 0 0 } \
+               {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retreuve policy"
+       return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+       -re "1\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test16
+
+# Description: (17) Accepts 4 for pw_min_classes.
+test "create-policy 17"
+proc test17 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+               {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retreuve policy"
+       return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+       -re "5\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test17
+
+# Description: (18) Rejects 5 for pw_min_classes.
+test "create-policy 18"
+proc test18 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+               {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test18
+
+# Description: (19) Rejects 0 for pw_history_num.
+test "create-policy 19"
+proc test19 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY KADM5_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test19
+
+# Description: (20) Accepts 1 for pw_history_num.
+test "create-policy 20"
+proc test20 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd  [format {
+       kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+               {KADM5_POLICY KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retreuve policy"
+       return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+       -re "1\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test20
+
+# Description: (21) Accepts 10 for pw_history_num.
+test "create-policy 21"
+proc test21 {} {
+    global test
+    global prompt
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+               {KADM5_POLICY KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+       -re "10\n$prompt$"              { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test21
+    
+# Description: (22) Fails for user with no access bits.
+test "create-policy 22"
+proc test22 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} test22
+
+# Description: (23) Fails for user with "get" but not "add".
+test "create-policy 23"
+proc test23 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} test23
+
+# Description: (24) Fails for user with "modify" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 24"
+proc test24 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} test24
+
+# Description: (25) Fails for user with "delete" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 25"
+proc test25 {} {
+    global test
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} test25
+
+# Description: Succeeds for user with "add".
+test "create-policy 26"
+proc test26 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test26
+
+# Description: Succeeds for user with "get" and "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 27"
+proc test27 {} {
+    global test
+
+    if {! (( ! [policy_exists "$test/a"]) ||
+          [delete_policy "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/get-add admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test27
+
+# Description: (28) Rejects null policy argument.
+# 01/24/94: pshuang: untried.
+test "create-policy 28"
+proc test28 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_create_policy $server_handle null {KADM5_POLICY}
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test28
+
+test "create-policy 30"
+proc test30 {} {
+    global test
+    one_line_fail_test [format {
+       kadm5_create_policy null [simple_policy "%s/a"] \
+               {KADM5_POLICY}
+    } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/crte-principal.exp b/src/lib/kadm5/unit-test/api.3/crte-principal.exp
new file mode 100644 (file)
index 0000000..774e204
--- /dev/null
@@ -0,0 +1,1336 @@
+load_lib lib.t
+api_exit
+api_start
+
+#test "create-principal 1"
+#
+#proc test1 {} {
+#      global test
+#      begin_dump
+#      one_line_fail_test [format {
+#          kadm5_create_principal $server_handle \
+#                  [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+#      } $test $test] "NOT_INIT"
+#      end_dump_compare "no-diffs"
+#}
+#test1
+
+# v2 create-principal 3 test, to avoid name conflict
+test "create-principal 1"
+proc test1 {} {
+    global test
+#    set prms_id 777
+#    setup_xfail {*-*-*} $prms_id
+    begin_dump
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} null
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"    
+}
+test1
+
+test "create-principal 2"
+
+proc test2 {} {
+    global test
+    begin_dump
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_create_principal $server_handle null \
+               {KADM5_PRINCIPAL} testpass
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"
+}
+test2
+
+test "create-principal 4"
+proc test4 {} {
+    global test
+
+    begin_dump    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} ""
+    } $test] "_Q_TOOSHORT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"     
+}
+test4
+
+test "create-principal 5"
+proc test5 {} {
+    global test
+    begin_dump    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle \
+               [simple_principal "%s/a"] {0x100001} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"    
+}
+test5
+
+test "create-principal 6"
+proc test6 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_LAST_PWD_CHANGE} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test6
+
+test "create-principal 7"
+proc test7 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MOD_TIME} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test7
+
+test "create-principal 8"
+proc test8 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MOD_NAME} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test8
+
+test "create-principal 9"
+proc test9 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MKVNO} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test9
+
+test "create-principal 10"
+proc test10 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_AUX_ATTRIBUTES} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test10
+
+test "create-principal 11"
+proc test11 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_POLICY_CLR} "%s/a"
+    } $test $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test11
+
+test "create-principal 12"
+proc test12 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+
+}
+if {$RPC} { test12 }
+
+test "create-principal 13"
+proc test13 {} {
+    global test
+    begin_dump        
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test13 }
+
+test "create-principal 14"
+proc test14 {} {
+    global test
+    begin_dump        
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test14 }
+
+test "create-principal 15"
+proc test15 {} {
+    global test
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"    
+}
+if {$RPC} { test15 }
+
+test "create-principal 16"
+proc test16 {} {
+    global test
+    begin_dump        
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+if {$RPC} { test16 }
+
+test "create-principal 17"
+proc test17 {} {
+    global test
+
+    begin_dump    
+    if {! (( [principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+               error_and_restart "$test: couldn't create principal \"$test/a\""
+               return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test] "DUP"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test17
+
+test "create-principal 18"
+proc test18 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle \
+               [princ_w_pol "%s/a" test-pol] \
+               {KADM5_PRINCIPAL KADM5_POLICY} tP
+    } $test] "_Q_TOOSHORT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"    
+}
+test18
+
+test "create-principal 19"
+proc test19 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle \
+               [princ_w_pol "%s/a" test-pol] \
+               {KADM5_PRINCIPAL KADM5_POLICY} testpassword
+    } $test] "_Q_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test19
+
+test "create-principal 20"
+proc test20 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle \
+               [princ_w_pol "%s/a" test-pol] \
+               {KADM5_PRINCIPAL KADM5_POLICY} Abyssinia
+    } $test] "_Q_DICT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test20
+
+test "create-principal 21"
+proc test21 {} {
+    global test
+
+    begin_dump    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_create_principal $server_handle \
+               [princ_w_pol "%s/a" non-existant-pol] \
+               {KADM5_PRINCIPAL KADM5_POLICY} NotinTheDictionary
+    } $test] "UNK_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    end_dump_compare "no-diffs"        
+}
+test21
+
+test "create-principal 23"
+proc test23 {} {
+    global test
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    one_line_succeed_test \
+           [format {kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK} $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test23
+
+test "create-principal 24"
+proc test24 {} {
+    global test
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/rename admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    one_line_succeed_test \
+           [format {kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK} $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test24 }
+
+
+test "create-principal 28"
+proc test28 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle \
+               [princ_w_pol "%s/a" test-pol] \
+               {KADM5_PRINCIPAL KADM5_POLICY} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+       -re "test-pol.*$prompt$"   { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test28
+
+test "create-principal 29"
+proc test29 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL KADM5_PRINC_EXPIRE_TIME} \
+               inTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 1\n"
+    expect {
+       -re "0.*$prompt$"   { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test29
+
+test "create-principal 30"
+proc test30 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+               NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0.*$prompt$"           { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test30
+
+test "create-principal 31"
+proc test31 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle \
+               [princ_w_pol "%s/a" test-pol-nopw] \
+               {KADM5_PRINCIPAL KADM5_POLICY \
+               KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0.*$prompt$"           { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test31
+
+test "create-principal 32"
+proc test32 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle \
+               [princ_w_pol "%s/a" test-pol] \
+               {KADM5_PRINCIPAL KADM5_POLICY \
+               KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+       error_and_restart "$test: cannot retrieve policy"
+       return
+    }
+
+    send "lindex \$principal 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting mod_date"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting mod_date"
+           return
+       }
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_expire"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_expire"
+           return
+       }
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_max_life"
+           return
+       }
+    }
+    if { $pw_expire != 0 } {
+       fail "$test: pw_expire $pw_expire should be 0"
+       return
+    } else {
+       pass "$test"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test32
+
+test "create-principal 33"
+proc test33 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle \
+               {"%s/a" 0 0 1234 0 null 0 0 0 0 null 0} \
+               {KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+               NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "1234.*$prompt$"        { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test33
+
+test "create-principal 34"
+proc test34 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle \
+               { "%s/a" 0 0 1234 0 null 0 0 0 0 test-pol-nopw 0} \
+               {KADM5_PRINCIPAL KADM5_POLICY \
+               KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "1234.*$prompt$"        { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test34
+
+test "create-principal 35"
+proc test35 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle \
+               {"%s/a" 0 0 1234 0 null 0 0 0 0 test-pol 0} \
+               {KADM5_PRINCIPAL KADM5_POLICY \
+               KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "1234.*$prompt$"        { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test35
+
+test "create-principal 36"
+proc test36 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle \
+               {"%s/a" 0 0 999999999 0 null 0 0 0 0 test-pol 0} \
+               {KADM5_PRINCIPAL KADM5_POLICY \
+               KADM5_PW_EXPIRATION} NotinTheDictionary
+    } $test]]} {    
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy} ]} {
+       error_and_restart "$test: cannot retrieve policy"
+       return
+    }
+
+    send "lindex \$principal 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting mod_date"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting mod_date"
+           return
+       }
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_expire"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_expire"
+           return
+       }
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_max_life"
+           return
+       }
+    }
+    if { $pw_expire != 999999999 } {
+       fail "$test: pw_expire is wrong"
+       return
+    } else {
+       pass "$test"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test36
+
+test "create-principal 37"
+proc test37 {} {
+    global test
+    global prompt
+
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0.*$prompt$"           { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test37
+
+test "create-principal 38"
+proc test38 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol-nopw] {KADM5_PRINCIPAL KADM5_POLICY} \
+               NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0.*$prompt$"           { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test38
+
+test "create-principal 39"
+proc test39 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol] {KADM5_PRINCIPAL KADM5_POLICY} \
+               NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if { ! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: cannot not retrieve principal"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+       error_and_restart "$test: cannot retrieve policy"
+       return
+    }
+    send "lindex \$principal 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting mod_date"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting mod_date"
+           return
+       }
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_expire"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_expire"
+           return
+       }
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_max_life"
+           return
+       }
+    }
+    if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+       fail "$test: pw_expire is wrong"
+       return
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test39
+
+test "create-principal 40"
+proc test40 {} {
+    global test
+    global prompt
+    
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+               NotinTheDictionary
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: can not retreive principal"
+       return;
+    }
+    send "lindex \$principal 4\n"
+    expect {
+       -re "0.*$prompt$"           { pass "$test" }
+       timeout                     { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test40
+
+test "create-principal 43"
+proc test43 {} {
+    global test
+    one_line_fail_test [format {
+       kadm5_create_principal null \
+                   [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+    } $test $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/destroy.exp b/src/lib/kadm5/unit-test/api.3/destroy.exp
new file mode 100644 (file)
index 0000000..a3e2bfc
--- /dev/null
@@ -0,0 +1,203 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "destroy 1"
+
+proc test1 {} {
+       global test
+       begin_dump
+       if {! [cmd {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+       }]} {
+               perror "$test: unexpected failure in init"
+               return
+       }
+       one_line_succeed_test {kadm5_destroy $server_handle}
+       end_dump_compare "no-diffs"
+}
+test1
+
+#test "destroy 2"
+#
+#proc test2 {} {
+#      global test
+#      begin_dump
+#      if {! [cmd {
+#          kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#                  $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#                  server_handle
+#      }]} {
+#          perror "$test: unexpected failure on init"
+#          return
+#      }
+#      if {! [cmd {kadm5_destroy $server_handle}]} {
+#              error_and_restart "$test: couldn't close database"
+#              return
+#      }
+#      one_line_fail_test \
+#              {kadm5_get_principal $server_handle admin principal} \
+#              "NOT_INIT"
+#      end_dump_compare "no-diffs"
+#}
+#test2
+
+#test "destroy 3"
+#proc test3 {} {
+#      global test
+#
+#      begin_dump
+#      if {! (( ! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+#          error_and_restart "$test couldn't delete principal \"$test/a\""
+#          return
+#      }
+#      if {! [cmd {
+#          kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#                  $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#                  server_handle
+#      }]} {
+#          perror "$test: unexpected failure on init"
+#          return
+#      }
+#      if {! [cmd {kadm5_destroy $server_handle}]} {
+#              error_and_restart "$test: couldn't close database"
+#              return
+#      }
+#      one_line_fail_test [format {
+#          kadm5_create_principal $server_handle \
+#                  [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+#      } $test $test] "NOT_INIT"
+#      end_dump_compare "no-diffs"
+#}
+#test3
+
+#test "destroy 4"
+#proc test4 {} {
+#      global test prompt
+#
+#      if {! (([principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+#              error_and_restart "$test: couldn't create principal \"$test/a\""
+#              return
+#      }
+#      begin_dump
+#      if {! ([cmd {
+#          kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#                  $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#                  server_handle
+#      }] &&
+#          [cmd [format {
+#              kadm5_get_principal $server_handle "%s/a" principal
+#          } $test]])} {
+#              error_and_restart "$test: error getting principal"
+#              return;
+#      }
+#      if {! [cmd {kadm5_destroy $server_handle}]} {
+#              error_and_restart "$test: couldn't close database"
+#              return
+#      }
+#      one_line_fail_test [format {
+#          kadm5_modify_principal $server_handle \
+#                  {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {KADM5_KVNO}
+#      } $test "77"] "NOT_INIT"
+#      end_dump_compare "no-diffs"
+#}
+#test4
+
+#test "destroy 5"
+#
+#proc test5 {} {
+#      global test
+#
+#      if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#              error_and_restart "$test: couldn't create principal \"$test/a\""
+#              return
+#      }
+#      begin_dump
+#      if {! [cmd {
+#          kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#                  $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#                  server_handle
+#      }]} {
+#          perror "$test: unexpected failure on init"
+#          return
+#      }
+#      if {! [cmd {kadm5_destroy $server_handle}]} {
+#              error_and_restart "$test: couldn't close database"
+#              return
+#      }
+#      one_line_fail_test [format {
+#          kadm5_delete_principal $server_handle "%s/a"
+#      } $test] "NOT_INIT"
+#      end_dump_compare "no-diffs"
+#}
+#test5
+
+#test  "destroy 6"
+#
+#proc test6 {} {
+#      global test
+#      begin_dump      
+#      one_line_fail_test {kadm5_destroy $server_handle} "NOT_INIT"
+#      end_dump_compare "no-diffs"     
+#}
+#test6
+
+
+#test  "destroy 7"
+#
+#proc test7 {} {
+#      global test
+#      begin_dump      
+#      if {! [cmd {
+#          kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#                  $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#                  server_handle
+#      }]} {
+#              perror "$test: unexpected failure in init"
+#              return
+#      }
+#      if {! [cmd {kadm5_destroy $server_handle}]} {
+#              error_and_restart "$test: couldn't close database"
+#      }
+#      one_line_fail_test {kadm5_destroy $server_handle} "NOT_INIT"
+#      end_dump_compare "no-diffs"     
+#}
+#test7
+
+test   "destroy 8"
+proc test8 {} {
+       global test
+       begin_dump      
+       if {! [cmd {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }]} {
+               perror "$test: unexpected failure in init"
+               return
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+       one_line_succeed_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+       end_dump_compare "no-diffs"             
+}
+test8
+
+test "destroy 9"
+proc test9 {} {
+       global test
+       one_line_fail_test {kadm5_destroy null} "BAD_SERVER_HANDLE"
+}
+test9
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/dlte-policy.exp b/src/lib/kadm5/unit-test/api.3/dlte-policy.exp
new file mode 100644 (file)
index 0000000..cecb5c3
--- /dev/null
@@ -0,0 +1,207 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "delete-policy 2"
+proc test2 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test \
+           {kadm5_delete_policy $server_handle ""} "BAD_POL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test2
+
+test "delete-policy 5"
+proc test5 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if ${RPC} test5
+
+test "delete-policy 6"
+proc test6 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if ${RPC} test6
+
+test "delete-policy 7"
+proc test7 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_policy $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} test7
+
+test "delete-policy 10"
+proc test10 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_delete_policy $server_handle  "%s/a"
+    } $test]]} {
+       fail "$test"
+       return
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    if { [policy_exists "$test/a"]} {
+       fail "$test"
+       return
+    }
+}
+test10
+
+test "delete-policy 12"
+proc test12 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+    if {! ((! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test unexecpted failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+               "%s/a"] {KADM5_PRINCIPAL KADM5_POLICY} \
+               NotinTheDictionary
+    } $test $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test \
+           {kadm5_delete_policy $server_handle test-pol} "POLICY_REF"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test12
+
+test "delete-policy 13"
+proc test13 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_policy null "%s/a"
+    } $test] "BAD_SERVER_HANDLE"
+}
+test13
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/dlte-principal.exp b/src/lib/kadm5/unit-test/api.3/dlte-principal.exp
new file mode 100644 (file)
index 0000000..f6d267f
--- /dev/null
@@ -0,0 +1,329 @@
+load_lib lib.t
+
+api_exit
+api_start
+
+#test "delete-principal 1"
+#proc test1 {} {
+#      global test
+#      one_line_fail_test [format {
+#          kadm5_delete_principal $server_handle "%s/a"
+#      } $test] "NOT_INIT"
+#}
+#test1
+
+test "delete-principal 2"
+proc test2 {} {
+    global test
+   
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+       error_and_restart "$test: couldn't delete principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test \
+           {kadm5_delete_principal $server_handle null} "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       error_and_restart "$test: unexpected failure in destroy"
+       return
+    }
+}
+test2
+
+test "delete-principal 5"
+proc test5 {} {
+    global test
+   
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+       error_and_restart "$test: couldn't delete principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test] "UNK_PRINC"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test5
+
+test "delete-principal 6"
+proc test6 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal_pol "$test/a" test-pol])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test6 }
+    
+       
+test "delete-principal 7"
+proc test7 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test7 }
+    
+       
+test "delete-principal 8"
+proc test8 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test8 }
+
+test "delete-principal 9"
+proc test9 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test9 }
+
+test "delete-principal 10"
+proc test10 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test] "AUTH_DELETE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test10 }
+
+test "delete-principal 11"
+proc test11 {} {
+    global test
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test]]} {
+       fail "$test: delete failed"
+       return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    if { [principal_exists "$test/a"] } {
+       fail "$test"
+       return
+    }
+}
+test11
+
+test "delete-principal 12"
+proc test12 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal_pol "$test/a" test-pol])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_delete_principal $server_handle "%s/a"
+    } $test]]} {
+       fail "$test: delete failed"
+       return
+    }
+    if { [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       fail "$test: principal still exists"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    send "lindex \$p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { [expr "$oldref - 1"] != $newref } {
+       fail "$test: policy reference count is wrong"
+       return;
+    }
+    pass "$test"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+
+test12
+
+test "delete-principal 13"
+proc test13 {} {
+       global test
+       one_line_fail_test [format {
+           kadm5_delete_principal null "%s/a"
+       } $test] "BAD_SERVER_HANDLE"
+}
+test13
+    
+return ""
+
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.3/get-policy.exp b/src/lib/kadm5/unit-test/api.3/get-policy.exp
new file mode 100644 (file)
index 0000000..c15ef0c
--- /dev/null
@@ -0,0 +1,199 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-policy 3"
+proc test3 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+           $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+       server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle "" p} "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test3
+
+test "get-policy 6"
+proc test6 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+           $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+           server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+           "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } test6
+
+test "get-policy 7"
+proc test7 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+           $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+           server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+           "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } test7
+
+test "get-policy 11"
+proc test11 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/get-pol StupidAdmin $KADM5_ADMIN_SERVICE \
+               null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test {kadm5_get_policy $server_handle test-pol p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test11
+
+test "get-policy 12"
+proc test12 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/get-pol StupidAdmin \
+               $KADM5_CHANGEPW_SERVICE null $KADM5_STRUCT_VERSION \
+               $KADM5_API_VERSION_3 server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test \
+           {kadm5_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test12
+
+test "get-policy 15"
+proc test15 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/pol StupidAdmin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test \
+           {kadm5_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test15
+
+test "get-policy 16"
+proc test16 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/pol StupidAdmin $KADM5_CHANGEPW_SERVICE \
+               null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test \
+           {kadm5_get_policy $server_handle test-pol-nopw p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test16
+
+test "get-policy 17"
+proc test17 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+           $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+           server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test {kadm5_get_policy $server_handle test-pol p}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test17
+
+test "get-policy 18"
+proc test18 {} {
+    global test
+
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+           "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } test18
+
+test "get-policy 21"
+proc test21 {} {
+    global test
+
+    one_line_fail_test {kadm5_get_policy null "pol1" p} "BAD_SERVER_HANDLE"
+}
+test21
diff --git a/src/lib/kadm5/unit-test/api.3/get-principal-v2.exp b/src/lib/kadm5/unit-test/api.3/get-principal-v2.exp
new file mode 100644 (file)
index 0000000..86c45f4
--- /dev/null
@@ -0,0 +1,250 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-principal 100"
+proc test100 {} {
+    global test prompt
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd {
+       kadm5_get_principal $server_handle testuser p \
+               {KADM5_PRINCIPAL_NORMAL_MASK}
+    }]} {
+       perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 16\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting num_keys"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting num_keys"
+           return
+       }
+    }
+    send "lindex \$p 17\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" { set num_tl $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting num_tl"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting num_tl"
+           return
+       }
+    }
+    send "lindex \$p 18\n"
+    expect {
+       -re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+       -re "\n$prompt" { set key_data {} }
+       timeout {
+           error_and_restart "$test: timeout getting key_data"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting key_data"
+           return
+       }
+    }
+    send "lindex \$p 19\n"
+    expect {
+       -re "({.*})\n$prompt" {set tl_data $expect_out(1,string) }
+       -re "\n$prompt" { set tl_data {} }
+       timeout {
+           error_and_restart "$test: timeout getting tl_data"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting tl_data"
+           return
+       }
+    }
+    
+    set failed 0
+    if {$num_keys != 0} {
+       fail "$test: num_keys $num_keys should be 0"
+       set failed 1
+    }
+    if {$num_tl != 0} {
+       fail "$test: num_tl $num_tl should be 0"
+       set failed 1
+    }
+    if {$key_data != {}} {
+       fail "$test: key_data $key_data should be {}"
+       set failed 1
+    }
+    if {$tl_data != "{}"} {
+       fail "$test: tl_data $tl_data should be empty"
+       set failed 1
+    }
+    if {$failed == 0} {
+       pass "$test"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test100
+
+proc test101_102 {rpc} {
+    global test prompt
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd {
+       kadm5_get_principal $server_handle testuser p \
+               {KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+    }]} {
+       perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 16\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting num_keys"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting num_keys"
+           return
+       }
+    }
+    send "lindex \$p 18\n"
+    expect {
+       -re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+       -re "\n$prompt" { set key_data {} }
+       timeout {
+           error_and_restart "$test: timeout getting key_data"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting key_data"
+           return
+       }
+    }
+
+    set failed 0
+    if {$num_keys != 3} {
+       fail "$test: num_keys $num_keys should be 3"
+       set failed 1
+    }
+    for {set i 0} {$i < $num_keys} {incr i} {
+       set key "[lindex [lindex $key_data $i] 2]"
+       if {($rpc && [string compare $key ""] != 0) ||
+           ((! $rpc) && [string compare $key ""] == 0)} {
+           fail "$test: key_data $key is wrong"
+           set failed 1
+           
+       }
+    }
+    if {$failed == 0} { pass "$test" }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test "get-principal 101" 
+if {$RPC} {test101_102 $RPC}
+test "get-principal 102" 
+if {! $RPC} {test101_102 $RPC}
+
+test "get-principal 103"
+proc test103 {} {
+    global test prompt
+
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               "{%s/a} 0 0 0 0 {%s/a} 0 0 0 0 null 0 0 0 0 0 0 1 {} {{999 6 foobar}}" \
+               {KADM5_TL_DATA}
+    } $test $test]]} {
+       fail "$test: cannot set TL_DATA"
+       return
+    }
+
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle {%s/a} p \
+               {KADM5_PRINCIPAL_NORMAL_MASK KADM5_TL_DATA}
+    } $test]]} {
+       perror "$test: unexpected failure in get_principal"
+    }
+    send "lindex \$p 17\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" { set num_tl $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting num_tl"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting num_tl"
+           return
+       }
+    }
+    send "lindex \$p 19\n"
+    expect {
+       -re "({.*})\n$prompt" {set tl_data $expect_out(1,string) }
+       -re "\n$prompt" { set tl_data {} }
+       timeout {
+           error_and_restart "$test: timeout getting tl_data"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting tl_data"
+           return
+       }
+    }
+    
+    if {$num_tl == 0} {
+       fail "$test: num_tl $num_tl should not be 0"
+    } elseif {$tl_data == "{{999 6 foobar}}"} {
+       pass "$test"
+    } else {
+       fail "$test: tl_data $tl_data should be {{999 6 foobar}}"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test103
+
+return ""
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.3/get-principal.exp b/src/lib/kadm5/unit-test/api.3/get-principal.exp
new file mode 100644 (file)
index 0000000..a33fdfe
--- /dev/null
@@ -0,0 +1,346 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "get-principal 1"
+proc test1 {} {
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test \
+           {kadm5_get_principal $server_handle null p KADM5_PRINCIPAL_NORMAL_MASK} "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test1
+
+test "get-principal 2"
+proc test2 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "UNK_PRINC"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test2
+
+test "get-principal 3"
+proc test3 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test3 }
+    
+test "get-principal 4"
+proc test4 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test4 }
+
+test "get-principal 5"
+proc test5 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test5 }
+
+test "get-principal 6"
+proc test6 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test6 }
+
+test "get-principal 7"
+proc test7 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test7 }
+
+    
+test "get-principal 8"
+proc test8 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+    } $test] "AUTH_GET"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test8 }
+
+    
+test "get-principal 9"
+proc test9 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test \
+           {kadm5_get_principal $server_handle admin/none p KADM5_PRINCIPAL_NORMAL_MASK} 
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test9
+
+test "get-principal 10"
+proc test10 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test \
+           {kadm5_get_principal $server_handle admin/none p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test10
+
+test "get-principal 11"
+proc test11 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/get p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test11
+
+test "get-principal 12"
+proc test12 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/get p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test12
+
+test "get-principal 13"
+proc test13 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/add p KADM5_PRINCIPAL_NORMAL_MASK} 
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test13
+
+test "get-principal 14"
+proc test14 {} {
+    global test
+    if {! [cmd {
+       kadm5_init admin/get-mod admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test {kadm5_get_principal $server_handle admin/add p KADM5_PRINCIPAL_NORMAL_MASK}
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test14
+
+test "get-principal 15"
+proc test15 {} {
+    one_line_fail_test \
+           {kadm5_get_principal null "admin" p KADM5_PRINCIPAL_NORMAL_MASK} "BAD_SERVER_HANDLE"
+}
+test15
+
+return ""
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.3/init-v2.exp b/src/lib/kadm5/unit-test/api.3/init-v2.exp
new file mode 100644 (file)
index 0000000..656f146
--- /dev/null
@@ -0,0 +1,515 @@
+load_lib lib.t
+
+api_exit
+api_start
+
+if ![info exists RESOLVE] {
+    set RESOLVE [findfile $objdir/../../../tests/resolve/resolve]
+}
+proc get_hostname { } {
+    global RESOLVE
+    global hostname
+    global localhostname
+    global domain
+
+    if {[info exists hostname] && [info exists localhostname]} {
+       return 1
+    }
+
+    catch "exec $RESOLVE -q >myname" exec_output
+    if ![string match "" $exec_output] {
+       send_log "$exec_output\n"
+       verbose $exec_output
+       send_error "ERROR: can't get hostname\n"
+       return 0
+    }
+    set file [open myname r]
+    if { [ gets $file hostname ] == -1 } {
+       send_error "ERROR: no output from hostname\n"
+       return 0
+    }
+    close $file
+    catch "exec rm -f myname" exec_output
+    regexp "^(\[^.\]*)\.(.*)$" $hostname foo localhostname domain
+
+    set hostname [string tolower $hostname]
+    set localhostname [string tolower $localhostname]
+    set domain [string tolower $domain]
+    verbose "hostname: $hostname; localhostname: $localhostname; domain $domain"
+
+    return 1
+}
+
+
+test "init 101"
+proc test101 {} {
+    global test
+    global hostname
+
+    get_hostname
+    tcl_cmd "set hostname $hostname"
+
+    # XXX Fix to work with a remote TEST_SERVER.  For now, make sure
+    # it fails in that case.
+    one_line_succeed_test {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_ADMIN_SERVER KADM5_CONFIG_KADMIND_PORT} [list $hostname 1751]] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }
+    one_line_fail_test {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_ADMIN_SERVER KADM5_CONFIG_KADMIND_PORT} [list $hostname 4]] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "RPC_ERROR"
+}
+if {$RPC} test101
+
+test "init 102"
+proc test102 {} {
+    global test
+
+    one_line_fail_test {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_ADMIN_SERVER} does.not.exist] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "BAD_SERVER_NAME"
+}
+if {$RPC} test102
+
+test "init 103"
+proc test103 {} {
+    global test
+
+    one_line_fail_test {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_DBNAME} /does-not-exist] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "ENOENT"
+}
+#if {! $RPC} test103
+if {! $RPC} {
+    send_user "UNTESTED: test103: test needs updating for DAL changes (see MIT RT ticket 3202)\n"
+    untested "test103: test needs updating for DAL changes (see MIT RT ticket 3202)"
+}
+
+
+test "init 106"
+proc test106 {} {
+    global test prompt
+
+    set prompting 0
+    send [string trim {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_MKEY_FROM_KBD} 1] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]
+    send "\n"
+    expect {
+       -re "\n\[^\n\]+:\[^\n\]*$" { set prompting 1}
+       -re "\nOK .*$prompt$" { fail "$test: premature success" }
+       -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+       timeout { fail "$test: timeout" }
+       eof { fail "$test: eof" }
+    }
+    if {$prompting} {
+       one_line_succeed_test mrroot
+    }
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+       error_and_restart "$test: couldn't close database"
+    }
+}
+if {! $RPC} test106
+
+test "init 107"
+proc test107 {} {
+    global test
+
+    one_line_fail_test {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_STASH_FILE} /does-not-exist] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "KDB_CANTREAD_STORED"
+}
+if {! $RPC} test107
+
+test "init 108"
+proc test108 {} {
+    global test
+
+    one_line_fail_test {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_MKEY_NAME} does/not/exist] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "KRB5_KDB_CANTREAD_STORED"
+}
+if {! $RPC} test108
+
+test "init 109-113"
+proc test109 {} {
+    global test prompt
+
+    delete_principal "$test/a"
+
+    # I'd like to specify flags explicitly and check them, as in the
+    # following config_params, but tcl gets mighty confused if I do and 
+    # I have no idea why.
+#              [config_params {KADM5_CONFIG_MAX_LIFE KADM5_CONFIG_MAX_RLIFE KADM5_CONFIG_EXPIRATION KADM5_CONFIG_FLAGS KADM5_CONFIG_ENCTYPES} {10 20 30 KRB5_KDB_DISALLOW_TGT_BASED {}} ]
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+               [config_params {KADM5_CONFIG_MAX_LIFE KADM5_CONFIG_MAX_RLIFE KADM5_CONFIG_EXPIRATION KADM5_CONFIG_ENCTYPES} {10 20 30 {}} ] \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       fail "$test: cannot init with max_life"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test]]} {
+       fail "$test: can not create principal"
+       return;
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" p \
+               {KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+    } $test]]} {
+       fail "$test: can not get principal"
+       return;
+    }
+    send "puts \$p\n"
+    expect {
+       -re "$prompt" { }
+       timeout {
+           error_and_restart "$test: timeout getting prompt"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting prompt"
+           return
+       }
+    }
+    send "lindex \$p 4\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting max_life"
+           return
+       }
+    }
+    send "lindex \$p 12\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set max_rlife $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting max_rlife"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting max_rlife"
+           return
+       }
+    }
+    send "lindex \$p 1\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set expiration $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting expiration"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting expiration"
+           return
+       }
+    }
+    send "lindex \$p 7\n"
+    expect {
+       -re "(\[A-Z_\]*)\n$prompt" {set flags $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting flags"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting flags"
+           return
+       }
+    }
+    # This sorta worries me.  Since the test is setting ENCTYPES to
+    # nothing, the principal has no keys.  That means that nothing is
+    # printed for the keys in the correct case; but it feels too
+    # likely that nothing will be printed in the case of some problem.
+    send "lindex \$p 18\n"
+    expect {
+       -re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+       -re "\n$prompt" { set key_data {} }
+       timeout {
+           error_and_restart "$test: timeout getting flags"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting flags"
+           return
+       }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+    if {$max_life == 10} {
+       pass "$test"
+    } else {
+       fail "$test: $max_life is not 10"
+    }
+    if {$max_rlife == 20} {
+       pass "$test"
+    } else {
+       fail "$test: $max_rlife is not 20"
+    }
+    if {$expiration == 30} {
+       pass "$test"
+    } else {
+       fail "$test: $expiration is not 30"
+    }
+    if {$flags == ""} {
+       pass "$test"
+    } else {
+       fail "$test: flags $flags are wrong"
+    }
+    if {$key_data == {}} {
+       pass "$test"
+    } else {
+       fail "$test: key_data $key_data is wrong"
+    }
+}
+if {! $RPC} test109
+
+test "init 116"
+proc test116 {} {
+    global test
+
+    delete_principal "$test/a"
+
+    if {! [cmd {kadm5_init admin/get-add admin $KADM5_ADMIN_SERVICE \
+           null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+           get_add_handle}]} {
+       error_and_restart "$test: couldn't init with admin/get-add"
+    }
+
+    if {! [cmd {kadm5_init admin/mod-delete admin $KADM5_ADMIN_SERVICE \
+           null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+           mod_delete_handle}]} {
+       error_and_restart "$test: couldn't init with admin/get-add"
+    }
+
+    one_line_succeed_test {
+       kadm5_get_principal $get_add_handle testuser p \
+               KADM5_PRINCIPAL_NORMAL_MASK
+    }
+    one_line_succeed_test [format {
+       kadm5_create_principal $get_add_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test]
+    one_line_fail_test { 
+       kadm5_modify_principal $get_add_handle [simple_principal testuser] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } "AUTH_MODIFY"
+    one_line_fail_test {
+       kadm5_delete_principal $get_add_handle testuser
+    } "AUTH_DELETE"
+
+    one_line_fail_test {
+       kadm5_get_principal $mod_delete_handle testuser p \
+               KADM5_PRINCIPAL_NORMAL_MASK
+    } "AUTH_GET"
+    one_line_fail_test [format {
+       kadm5_create_principal $mod_delete_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} testpass
+    } $test] "AUTH_ADD"
+    one_line_succeed_test { 
+       kadm5_modify_principal $mod_delete_handle [simple_principal testuser] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    }
+    one_line_succeed_test [format {
+       kadm5_delete_principal $mod_delete_handle "%s/a"
+    } $test]
+
+    if {! [cmd {kadm5_destroy $get_add_handle}]} {
+       error_and_restart "$test: couldn't close get_add_handle"
+    }
+    if {! [cmd {kadm5_destroy $mod_delete_handle}]} {
+       error_and_restart "$test: couldn't close mod_delete_handle"
+    }
+}
+if {$RPC} test116
+
+test "init 117"
+proc test117 {} {
+    global test env prompt
+
+    if {[catch "exec grep max_life $env(KRB5_KDC_PROFILE)"] != 1} {
+       warning \
+          "$test: max_life in $env(KRB5_KDC_PROFILE), cannot perform test"
+       return
+    }
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+        [delete_principal "$test/a"])} {
+        error_and_restart "$test: couldn't delete principal \"$test/a\""
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       fail "$test: unexpected failure in init"
+       return
+    }
+
+    if {! [cmd [format {
+       kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL} "%s/a"
+    } $test $test]]} {
+       perror "$test: unexpected failure creating principal"
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_MAX_LIFE
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting max_life"
+           return
+       }
+    }
+    
+    if {$max_life == 86400} {
+       pass "$test"
+    } else {
+       fail "$test: max_life $max_life should be 86400"
+    }
+
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+       error_and_restart "$test: couldn't close server_handle"
+    }
+}
+test117
+    
+send "puts \$KADM5_ADMIN_SERVICE\n"
+expect {
+    -re "(\[a-zA-Z/@\]+)\n$prompt" {
+       set KADM5_ADMIN_SERVICE $expect_out(1,string) 
+    }
+    default {
+       error_and_restart "$test: timeout/eof getting admin_service"
+       return
+    }
+}
+
+send "puts \$KADM5_CHANGEPW_SERVICE\n"
+expect {
+    -re "(\[a-zA-Z/@\]+)\n$prompt" {
+       set KADM5_CHANGEPW_SERVICE $expect_out(1,string) 
+    }
+    default {
+       error_and_restart "$test: timeout/eof getting changepw_service"
+       return
+    }
+}
+
+test "init 150"
+proc test150 {} {
+    global test KADM5_ADMIN_SERVICE
+
+    kdestroy
+    kinit testuser notathena "-S $KADM5_ADMIN_SERVICE"
+    one_line_succeed_test {
+       kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+               null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }
+    kdestroy
+}
+if {$RPC} test150
+
+test "init 151"
+proc test151 {} {
+    global test KADM5_CHANGEPW_SERVICE
+
+    kdestroy
+    kinit testuser notathena "-S $KADM5_CHANGEPW_SERVICE"
+    one_line_succeed_test {
+       kadm5_init_with_creds testuser null $KADM5_CHANGEPW_SERVICE \
+               null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }
+    kdestroy
+}
+if {$RPC} test151
+
+test "init 152"
+proc test152 {} {
+    global test KADM5_ADMIN_SERVICE
+
+    kdestroy
+    one_line_fail_test {
+       kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+               null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "KRB5_FCC_NOFILE"
+}
+if {$RPC} test152
+
+test "init 153"
+proc test153 {} {
+    global test KADM5_ADMIN_SERVICE
+
+    kinit testuser notathena
+    one_line_fail_test {
+       kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+               null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "KRB5_CC_NOTFOUND"
+}
+if {$RPC} test153
+
+test "init 154"
+proc test154 {} {
+    global test env
+
+    set orig $env(KRB5_KDC_PROFILE)
+    set env(KRB5_KDC_PROFILE) /does-not-exist
+    api_exit; api_start
+    set env(KRB5_KDC_PROFILE) $orig
+
+    one_line_fail_test {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } "ENOENT"
+
+    api_exit; lib_start_api
+}
+if {0 && ! $RPC} test154
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/init.exp b/src/lib/kadm5/unit-test/api.3/init.exp
new file mode 100644 (file)
index 0000000..b324df8
--- /dev/null
@@ -0,0 +1,732 @@
+load_lib lib.t
+
+# Assumptions:
+# 
+# Principal "admin" exists, with "get", "add", "modify" and "delete"
+#   access bits and password "admin".
+# The string "not-the-password" isn't the password of any user in the database.
+# Database master password is "mrroot".
+
+api_exit
+api_start
+test "init 1"
+
+one_line_fail_test_nochk \
+       {kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+       [config_params {KADM5_CONFIG_REALM} {""}] \
+        $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 server_handle}
+
+test "init 2"
+
+one_line_fail_test_nochk \
+       {kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+       [config_params {KADM5_CONFIG_REALM} {@}] \
+        $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 server_handle}
+
+test "init 2.5"
+
+one_line_fail_test_nochk \
+       {kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+       [config_params {KADM5_CONFIG_REALM} {BAD.REALM}] \
+        $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 server_handle}
+
+test "init 3"
+
+proc test3 {} {
+    global test
+    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+       error_and_restart "$test: couldn't create principal \"$test/a\""
+       return
+    }
+    one_line_fail_test_nochk [format {
+       kadm5_init admin admin "%s/a" null $KADM5_STRUCT_VERSION \
+               $KADM5_API_VERSION_3 server_handle
+    } $test]
+}
+if {$RPC} { test3 }
+
+test "init 4"
+
+proc test4 {} {
+    global test
+       if {! ((! [principal_exists "$test/a"]) || 
+         [delete_principal "$test/a"])} {
+               error_and_restart "$test: couldn't delete principal \"$test/a\""
+               return
+       }
+               
+       one_line_fail_test_nochk [format {
+           kadm5_init admin admin "%s/a" null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       } $test]
+}
+if {$RPC} { test4 }
+
+test "init 5"
+
+if {$RPC} {
+    one_line_fail_test_nochk {
+       kadm5_init admin admin admin null $KADM5_STRUCT_VERSION \
+               $KADM5_API_VERSION_3 server_handle
+    }
+}
+
+test "init 6"
+
+proc test6 {} {
+    global test
+
+    send "kadm5_init admin null \$KADM5_ADMIN_SERVICE null \$KADM5_STRUCT_VERSION \$KADM5_API_VERSION_3 server_handle\n"
+
+    expect {
+       -re "assword\[^\r\n\]*:" { }
+       eof {
+               fail "$test: eof instead of password prompt"
+               api_exit
+               api_start
+               return
+       }
+       timeout {
+           fail "$test: timeout instead of password prompt"
+           return
+       }
+    }
+    one_line_succeed_test "admin"
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+       error_and_restart "$test: couldn't close database"
+    }
+}
+if { $RPC } { test6 } 
+
+test "init 7"
+proc test7 {} {
+    global test
+
+    send "kadm5_init admin \"\" \$KADM5_ADMIN_SERVICE null \$KADM5_STRUCT_VERSION \$KADM5_API_VERSION_3 server_handle\n"
+
+    expect {
+       -re "assword\[^\r\n\]*:" { }
+       -re "key:$" { }
+       eof {
+               fail "$test: eof instead of password prompt"
+               api_exit
+               api_start
+               return
+       }
+       timeout {
+           fail "$test: timeout instead of password prompt"
+           return
+       }
+    }
+    one_line_succeed_test "admin"
+    if {! [cmd {kadm5_destroy $server_handle}]} {
+       error_and_restart "$test: couldn't close database"
+    }
+}
+if { $RPC } { test7 } 
+
+test "init 8"
+
+proc test8 {} {
+    global test
+       if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+               error_and_restart "$test: couldn't create principal \"$test/a\""
+               return
+       }
+       one_line_fail_test_nochk [format {
+           kadm5_init "%s/a" admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       } $test]
+}
+if {$RPC} { test8 }
+
+test "init 9"
+
+if {$RPC} {
+    global test
+  one_line_fail_test_nochk {
+      kadm5_init admin not-the-password $KADM5_ADMIN_SERVICE null \
+             $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+             server_handle
+  }
+}
+
+test "init 10"
+
+proc test10 {} {
+       global test
+#      set prms_id 562
+#      setup_xfail {*-*-*} $prms_id
+       one_line_fail_test_nochk {
+           kadm5_init null admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+}
+test10
+
+#test "init 11"
+#
+#proc test11 {} {
+#      global test
+#      set prms_id 563
+#      setup_xfail {*-*-*} $prms_id
+#      one_line_fail_test_nochk {
+#          kadm5_init "" admin $KADM5_ADMIN_SERVICE null \
+#                  $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#                  server_handle
+#      }
+#}
+#test11
+
+test "init 12"
+
+proc test12 {} {
+       global test
+    one_line_fail_test_nochk [format {
+       kadm5_init "%s/a" admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } $test]
+}
+if {$RPC} { test12 }
+
+test "init 13"
+
+proc test13 {} {
+       global test
+    one_line_fail_test_nochk [format {
+       kadm5_init "%s/a@SECURE-TEST.OV.COM" admin \
+               $KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION \
+               $KADM5_API_VERSION_3 server_handle
+    } $test]
+}
+if {$RPC} { test13 }
+
+test "init 14"
+
+proc test14 {} {
+       global test
+    one_line_fail_test_nochk [format {
+       kadm5_init "%s/a@BAD.REALM" admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } $test]
+}
+if {$RPC} { test14 }
+
+test "init 15"
+
+if {$RPC} {
+    one_line_fail_test_nochk {
+       kadm5_init admin@BAD.REALM admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }
+}
+
+test "init 16"
+
+proc test16 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+test16
+
+test "init 17"
+
+proc test17 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin@SECURE-TEST.OV.COM admin \
+                   $KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION \
+                   $KADM5_API_VERSION_3 server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+test17
+
+test "init 18"
+
+proc test18 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+test18
+
+test "init 19"
+
+proc test19 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin@SECURE-TEST.OV.COM admin \
+                   $KADM5_ADMIN_SERVICE \
+                   [config_params {KADM5_CONFIG_REALM} {SECURE-TEST.OV.COM}] \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+test19
+
+test "init 20"
+
+proc test20 {} {
+       global test
+  if {! [cmd {
+      kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+             $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+             server_handle
+  }]} {
+               error_and_restart "$test: couldn't init database"
+               return
+       }
+       one_line_succeed_test \
+               {kadm5_get_principal $server_handle admin principal KADM5_PRINCIPAL_NORMAL_MASK}
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+test20
+
+#test "init 21"
+#
+#proc test21 {} {
+#    global test
+#    if {! [cmd {
+#      kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+#              $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#              server_handle
+#    }]} {
+#      error_and_restart "$test: couldn't init database"
+#      return
+#    }
+#    one_line_fail_test_nochk {
+#      kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#              $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#              server_handle
+#    }
+#    if {! [cmd {kadm5_destroy $server_handle}]} {
+#      error_and_restart "$test: couldn't close database"
+#    }
+#}
+#test21
+
+
+# proc test22 {} {
+#      global test prompt
+#      set prompting 0
+#      send [string trim {
+#          kadm5_init admin null null null $KADM5_STRUCT_VERSION \
+#                  $KADM5_API_VERSION_3 server_handle
+#      }]
+#      send "\n"
+#      expect {
+#          -re ":$" { set prompting 1}
+#          -re "\nOK .*$prompt$" { fail "$test: premature success" }
+#          -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+#              timeout { fail "$test: timeout" }
+#              eof { fail "$test: eof" }
+#      }
+#      if {$prompting} {
+#          one_line_succeed_test mrroot
+#      }
+#      if {! [cmd {kadm5_destroy $server_handle}]} {
+#          error_and_restart "$test: couldn't close database"
+#      }
+# }
+# if {! $RPC} { test22 }
+# 
+# test "init 22.5"
+# proc test225 {} {
+#      global test prompt
+#      set prompting 0
+#      send [string trim {
+#          kadm5_init admin null null null $KADM5_STRUCT_VERSION \
+#                  $KADM5_API_VERSION_3 server_handle
+#      }]
+#      send "\n"
+#      expect {
+#          -re ":$" { set prompting 1}
+#          -re "\nOK .*$prompt$" { fail "$test: premature success" }
+#          -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+#              timeout { fail "$test: timeout" }
+#              eof { fail "$test: eof" }
+#      }
+#      if {$prompting} {
+#          one_line_succeed_test mrroot
+#      }
+#      if {! [cmd {kadm5_destroy $server_handle}]} {
+#          error_and_restart "$test: couldn't close database"
+#      }
+# }
+# if {! $RPC} { test225 }
+
+test "init 23"
+
+proc test23 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin not-the-password $KADM5_ADMIN_SERVICE \
+                   null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+if {! $RPC} { test23 }
+
+test "init 24"
+
+proc test24 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin admin null null $KADM5_STRUCT_VERSION \
+                   $KADM5_API_VERSION_3 server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+if {! $RPC} { test24 }
+
+test "init 25"
+
+proc test25 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin admin foobar null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+if {! $RPC} { test25 }
+
+test "init 26"
+
+#proc test26 {} {
+#      global test
+#
+#      api_exit
+#      api_start
+#      one_line_fail_test_nochk {
+#          kadm5_get_principal $server_handle admin principal
+#      }
+#}
+#test26
+
+#test "init 27"
+#
+#proc test27 {} {
+#      global test
+#
+#      if {! ((! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+#              error_and_restart "$test: couldn't delete principal \"$test/a\""
+#              return
+#      }
+#      begin_dump
+#      if {[cmd [format {
+#          kadm5_create_principal $server_handle [simple_principal \
+#                  "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+#      } $test $test]]} {
+#              fail "$test: unexpected success in add"
+#              return
+#      }
+#      end_dump_compare "no-diffs"
+#}
+#test27
+
+#test "init 28"
+#
+#proc test28 {} {
+#    global test prompt
+#
+#    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#      error_and_restart "$test: couldn't create principal \"$test/a\""
+#      return
+#    }
+#    begin_dump
+#    if {! ([cmd {
+#      kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+#              $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+#              server_handle
+#    }] && [cmd [format {
+#      kadm5_get_principal $server_handle "%s/a" principal
+#    } $test]])} {
+#      error_and_restart "$test: error getting principal"
+#      return;
+#    }
+#    send "lindex \$principal 8\n"
+#    expect {
+#      -re "\n(\[0-9\]+).*$prompt$" {set kvno $expect_out(1,string) }
+#      timeout {
+#          error_and_restart "$test: timeout getting principal kvno"
+#          return
+#      }
+#      eof {
+#          error_and_restart "$test: eof getting principal kvno"
+#          return
+#      }
+#    }
+#    api_exit
+#    api_start
+#    set new_kvno [expr "$kvno + 1"]
+#    if {[cmd [format {
+#      kadm5_modify_principal $server_handle \
+#              {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {KADM5_KVNO}
+#    } $test $new_kvno]]} {
+#      fail "$test: unexpected success in modify"
+#      return;
+#    }
+#    end_dump_compare "no-diffs"
+#}
+#test28
+
+#test "init 29"
+#
+#proc test29 {} {
+#    global test
+#
+#    if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+#      error_and_restart "$test: couldn't create principal \"$test/a\""
+#      return
+#    }
+#    begin_dump
+#    if {[cmd [format {
+#      kadm5_delete_principal $server_handle "%s/a"
+#    } $test]]} {
+#      fail "$test: unexpected success in delete"
+#      return
+#    }
+#    end_dump_compare "no-diffs"
+#}
+#test29
+
+test "init 30"
+proc test30 {} {
+       global test
+       if {[cmd {
+           kadm5_init admin foobar $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }]} {
+               error_and_restart "$test: unexpected success"
+               return
+       }
+       one_line_succeed_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+if ${RPC} { test30 }
+
+test "init 31"
+proc test31 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $bad_struct_version_mask $KADM5_API_VERSION_3 \
+                   server_handle
+       } "BAD_STRUCT_VERSION" 
+}
+test31
+
+test "init 32"
+proc test32 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $no_struct_version_mask $KADM5_API_VERSION_3 \
+                   server_handle
+       } "BAD_STRUCT_VERSION" 
+}
+test32
+
+test "init 33"
+proc test33 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $old_struct_version $KADM5_API_VERSION_3 \
+                   server_handle
+       } "OLD_STRUCT_VERSION" 
+}
+test33
+
+test "init 34"
+proc test34 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $new_struct_version $KADM5_API_VERSION_3 \
+                   server_handle
+       } "NEW_STRUCT_VERSION" 
+}
+test34
+
+test "init 35"
+proc test35 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $bad_api_version_mask \
+                   server_handle
+       } "BAD_API_VERSION" 
+}
+test35
+
+test "init 36"
+proc test36 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $no_api_version_mask \
+                   server_handle
+       } "BAD_API_VERSION" 
+}
+test36
+
+test "init 37"
+proc test37 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $old_api_version \
+                   server_handle
+       } "OLD_LIB_API_VERSION" 
+}
+if { $RPC } test37
+
+test "init 38"
+proc test38 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $old_api_version \
+                   server_handle
+       } "OLD_SERVER_API_VERSION" 
+}
+if { ! $RPC } test38
+
+test "init 39"
+proc test39 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $new_api_version \
+                   server_handle
+       } "NEW_LIB_API_VERSION" 
+}
+if { $RPC } test39
+
+test "init 40"
+proc test40 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $new_api_version \
+                   server_handle
+       } "NEW_SERVER_API_VERSION" 
+}
+if { ! $RPC } test40
+
+test "init 41"
+proc test41 {} {
+       global test
+       one_line_fail_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_API_VERSION_3 $KADM5_STRUCT_VERSION \
+                   server_handle
+       } "BAD_"
+}
+test41
+
+test "init 42"
+proc test42 {} {
+       global test
+       one_line_succeed_test {
+           kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+                   $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+                   server_handle
+       }
+       if {! [cmd {kadm5_destroy $server_handle}]} {
+               error_and_restart "$test: couldn't close database"
+       }
+}
+test42
+
+
+proc test45_46 {service} {
+    global test kadmin_local env
+
+    spawn $kadmin_local -q "delprinc -force $service"
+    expect {
+       -re "Principal .* deleted." {}
+       default {
+           perror "kadmin.local delprinc failed\n";
+       }
+    }
+    expect eof
+    wait
+
+    one_line_fail_test [concat {kadm5_init admin admin } \
+           $service \
+           { null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+           server_handle}] "SECURE_PRINC_MISSING"
+
+    # this leaves the keytab with an incorrect entry
+    spawn $kadmin_local -q "ank -randkey $service"
+    expect eof
+    wait
+
+    # restart the api so it gets a new ccache
+    api_exit
+    api_start
+}
+
+if {$RPC} {
+    test "init 45"
+
+    test45_46 ovsec_adm/admin
+
+    test "init 46"
+
+    test45_46 ovsec_adm/changepw
+
+    # re-extract the keytab so it is right
+    exec rm $env(K5ROOT)/ovsec_adm.srvtab
+    exec $env(MAKE_KEYTAB) -princ ovsec_adm/admin -princ ovsec_adm/changepw \
+           -princ kadmin/admin -princ kadmin/changepw \
+           $env(K5ROOT)/ovsec_adm.srvtab
+}
+
+return ""
+
diff --git a/src/lib/kadm5/unit-test/api.3/mod-policy.exp b/src/lib/kadm5/unit-test/api.3/mod-policy.exp
new file mode 100644 (file)
index 0000000..599e7d3
--- /dev/null
@@ -0,0 +1,739 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "modify-policy 2"
+proc test2 {} {
+    global test
+
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test2 }
+
+test "modify-policy 4"
+proc test4 {} {
+    global test
+    
+    if {! ([policy_exists "$test/a"] ||
+          [create_policy "$test/a"])} {
+            error_and_restart "$test: couldn't create policy \"$test/a\""
+            return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_REF_COUNT}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+        perror "$test: unexpected failure in destroy"
+        return
+    }
+}
+test4
+
+test "modify-policy 8"
+proc test8 {} {
+    global test
+#    set prms_id 744
+#    setup_xfail {*-*-*} $prms_id
+
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_modify_policy $server_handle [simple_policy ""] \
+               {KADM5_PW_MAX_LIFE}
+    } "BAD_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test8
+
+test "modify-policy 9"
+proc test9 {} {
+    global test
+    global prompt
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MIN_LIFE}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test9
+
+test "modify-policy 10"
+proc test10 {} {
+    global test
+    global prompt
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle {"%s/a" 32 0 0 0 0 0 0 0 0} \
+               {KADM5_PW_MIN_LIFE}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 1\n"
+    expect {
+       -re "32\n$prompt$"              { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test10
+
+
+test "modify-policy 11"
+proc test11 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MAX_LIFE}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test11
+
+test "modify-policy 12"
+proc test12 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 32 0 0 0 0 0 0 0} \
+               {KADM5_PW_MAX_LIFE}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 2\n"
+    expect {
+       -re "32\n$prompt$"              { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test12
+
+test "modify-policy 13"
+proc test13 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MIN_LENGTH}
+    } $test] "BAD_LENGTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test13
+
+test "modify-policy 14"
+proc test14 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 8 0 0 0 0 0 0} \
+               {KADM5_PW_MIN_LENGTH}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 3\n"
+    expect {
+       -re "8\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test14
+
+test "modify-policy 15"
+proc test15 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test15
+
+test "modify-policy 16"
+proc test16 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 1 0 0 0 0 0} \
+               {KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+       -re "1\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test16
+
+test "modify-policy 17"
+proc test17 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a"])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 5 0 0 0 0 0} \
+               {KADM5_PW_MIN_CLASSES}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 4\n"
+    expect {
+       -re "5\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test17
+
+test "modify-policy 18"
+proc test18 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 6 0 0 0 0 0} \
+               {KADM5_PW_MIN_CLASSES}
+    } $test] "BAD_CLASS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test18
+
+test "modify-policy 19"
+proc test19 {} {
+    global test
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_HISTORY_NUM}
+    } $test] "BAD_HISTORY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test19
+
+test "modify-policy 20"
+proc test20 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 0 1 0 0 0 0} \
+               {KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+       -re "1\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test20
+
+test "modify-policy 21"
+proc test21 {} {
+    global test
+    global prompt
+    
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 0 10 0 0 0 0} \
+               {KADM5_PW_HISTORY_NUM}
+    } $test]]} {
+       fail $test
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_policy $server_handle "%s/a" policy
+    } $test]]} {
+       fail "$test: can not retrieve policy"
+       return
+    }
+    send "lindex \$policy 5\n"
+    expect {
+       -re "10\n$prompt$"              { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test21
+
+test "modify-policy 22"
+proc test22 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} test22
+
+test "modify-policy 23"
+proc test23 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MAX_LIFE}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} test23
+
+test "modify-policy 26"
+proc test26 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+               {KADM5_PW_MAX_LIFE}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test26
+
+test "modify-policy 30"
+proc test30 {} {
+    global test
+
+    one_line_fail_test [format {
+       kadm5_modify_policy null [simple_policy "%s/a"] \
+               {KADM5_PW_MAX_LIFE}
+    } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+test "modify-policy 31"
+proc test31 {} {
+    global test
+    if {! ((  [policy_exists "$test/a"]) ||
+          [create_policy "$test/a" ])} {
+           error_and_restart "$test: couldn't create policy \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 0 0 0 2 0 0} \
+               {KADM5_PW_MAX_FAILURE}
+    } $test]
+    one_line_succeed_test [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 1 0 0 0 90 0} \
+               {KADM5_PW_FAILURE_COUNT_INTERVAL}
+    } $test]
+    one_line_succeed_test [format {
+       kadm5_modify_policy $server_handle {"%s/a" 0 0 0 1 0 0 0 0 180} \
+               {KADM5_PW_LOCKOUT_DURATION}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test31
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/mod-principal-v2.exp b/src/lib/kadm5/unit-test/api.3/mod-principal-v2.exp
new file mode 100644 (file)
index 0000000..4abbeb5
--- /dev/null
@@ -0,0 +1,115 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "modify-principal 100-105"
+proc test100_104 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+
+    set origtest "$test"
+
+    test "modify-principal 100"
+    one_line_succeed_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MAX_RLIFE}
+    } $origtest]
+
+    test "modify-principal 101"
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_LAST_SUCCESS}
+    } $origtest] "BAD_MASK"
+
+    test "modify-principal 102"
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_LAST_FAILED}
+    } $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 {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_KEY_DATA}
+    } $origtest] "BAD_MASK"
+
+    test "modify-principal 105"
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle \
+            "{%s/a} 0 0 0 0 {%s/a} 0 0 0 0 null 0 0 0 0 0 0 1 {} {{1 1 x}}" \
+               {KADM5_TL_DATA}
+    } $origtest $origtest] "BAD_TL_TYPE"
+
+    test "modify-principal 100,104"
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               "{%s/a} 0 0 0 0 {%s/a} 0 0 0 0 null 0 88 0 0 0 0 1 {} {{990 6 foobar}}" \
+               {KADM5_MAX_RLIFE KADM5_TL_DATA}
+    } $origtest $origtest]]} {
+       fail "$test: cannot set MAX_RLIFE or TL_DATA"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal {KADM5_PRINCIPAL_NORMAL_MASK KADM5_TL_DATA}
+    } $origtest]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 12\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set rlife $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting rlife"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting rlife"
+           return
+       }
+    }
+    send "lindex \$principal 19\n"
+    expect {
+       -re "\(\{.*\}\)\n$prompt$" {set tl $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting tl_data"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting tl_data"
+           return
+       }
+    }
+    if {($rlife == 88) && ($tl == "{{990 6 foobar}}")} {
+       pass "$test"
+    } else {
+       fail "$test: $rlife should be 88, $tl should be {{990 6 foobar}}"
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test100_104
diff --git a/src/lib/kadm5/unit-test/api.3/mod-principal.exp b/src/lib/kadm5/unit-test/api.3/mod-principal.exp
new file mode 100644 (file)
index 0000000..25fb272
--- /dev/null
@@ -0,0 +1,1971 @@
+load_lib lib.t
+api_exit
+api_start
+
+#test "modify-principal 1"
+#proc test1 {} {
+#      global test
+#      one_line_fail_test [format {
+#          kadm5_modify_principal $server_handle [simple_principal \
+#                  "%s/a"] {KADM5_PW_EXPIRATION}
+#      } $test] "NOT_INIT"
+#}
+#test1
+
+test "modify-principal 2"
+proc test2 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MODIFY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test2 }
+
+test "modify-principal 4"
+proc test4 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINCIPAL}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test4
+
+
+test "modify-principal 5"
+proc test5 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_LAST_PWD_CHANGE}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test5
+
+test "modify-principal 6"
+proc test6 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MOD_TIME}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test6
+
+test "modify-principal 7"
+proc test7 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MOD_NAME}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test7
+
+test "modify-principal 8"
+proc test8 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MKVNO}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test8
+
+test "modify-principal 9"
+proc test9 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_AUX_ATTRIBUTES}
+    } $test] "BAD_MASK"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test9
+
+test "modify-principal 10"
+proc test10 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test] "UNK_PRINC"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test10
+
+test "modify-principal 11"
+proc test11 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test11 }
+
+test "modify-principal 12"
+proc test12 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test12 }
+
+test "modify-principal 13"
+proc test13 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test13 }
+
+test "modify-principal 14"
+proc test14 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test] "AUTH_MOD"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test14 }
+
+test "modify-principal 15"
+proc test15 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test15
+
+test "modify-principal 17"
+proc test17 {} {
+    global test
+    if {! (( [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               no-policy] {KADM5_POLICY}
+    } $test] "UNK_POLICY"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test17
+
+test "modify-principal 18"
+proc test18 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { !( [create_principal "$test/a"])} {
+       error_and_restart "$test: could not create principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol] {KADM5_POLICY}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+       -re "test-pol\n$prompt$"        { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { [expr "$oldref + 1"] != $newref } {
+       fail "$test: policy reference count is wrong"
+       return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test18
+
+test "modify-principal 19"
+proc test19 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { !( [create_principal "$test/a"])} {
+       error_and_restart "$test: could not create principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol] {KADM5_POLICY}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+       -re "test-pol\n$prompt$"        { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { [expr "$oldref + 1"] != $newref } {
+       fail "$test: policy reference count is wrong"
+       return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test19
+
+test "modify-principal 20"
+proc test20 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+       error_and_restart "$test: could not create principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]}  {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_POLICY_CLR}
+    } $test]]} {
+       perror "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+       -re "test-pol\n$prompt$"        { fail "$test" }
+       -re "null\n$prompt$"            { pass "$test" }
+       timeout                         { pass "$test" }
+    }
+    send "lindex \$p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    
+    send "lindex \$p2 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { [expr "$oldref - 1"] != $newref } {
+       fail "$test: policy reference count is wrong"
+       return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test20
+
+test "modify-principal 21"
+proc test21 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+       error_and_restart "$test: could not create principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol old_p1}]}  {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol-nopw old_p2}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol-nopw] {KADM5_POLICY}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$old_p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    send "lindex \$old_p2 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set old_p2_ref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol new_p1}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol-nopw new_p2}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    
+    send "lindex \$new_p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    send "lindex \$new_p2 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set new_p2_ref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { [expr "$old_p1_ref - 1"] != $new_p1_ref } {
+       fail "$test: policy reference count is wrong"
+       return;
+    }
+    if { [expr "$old_p2_ref + 1"] != $new_p2_ref } {
+       fail "$test: policy reference count is wrong"
+       return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test21
+
+test "modify-principal 21.5"
+proc test21.5 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+       error_and_restart "$test: could not create principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol old_p1}]}  {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol] {KADM5_POLICY}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$old_p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol new_p1}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    
+    send "lindex \$new_p1 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+
+    if {$old_p1_ref != $new_p1_ref} {
+       fail "$test: policy reference count changed ($old_p1_ref to $new_p1_ref)"
+       return
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test21.5
+
+test "modify-principal 22"
+proc test22 {} {
+    global test
+    global prompt
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PW_EXPIRATION}
+    } $test]]} {
+       fail "$test: modifiy failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test22
+
+test "modify-principal 23"
+proc test23 {} {
+    global test
+    global prompt
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal_pol "$test/a" test-pol-nopw])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PW_EXPIRATION}
+    } $test]]} {
+       fail "$test: modifiy failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test23
+
+test "modify-principal 24"
+proc test24 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal_pol "$test/a" "test-pol" ])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       error_and_restart "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PW_EXPIRATION}
+    } $test]]} {
+       fail "$test: could not modify principal"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_get_policy $server_handle %s policy
+    } test-pol]]} {
+       error_and_restart "$test: cannot retrieve policy"
+       return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting mod_date"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_mod_date"
+           return
+       }
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_expire"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_expire"
+           return
+       }
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_max_life"
+           return
+       }
+    }
+    if { $pw_expire != 0 } {
+       fail "$test: pw_expire $pw_expire should be 0"
+       return
+    } else {
+       pass "$test"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} { 
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test24
+
+test "modify-principal 25"
+proc test25 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "1234\n$prompt$"            { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test25
+
+test "modify-principal 26"
+proc test26 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal_pol "$test/a" "test-pol-nopw" ])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "1234\n$prompt$"            { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test26
+
+test "modify-principal 27"
+proc test27 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal_pol "$test/a" "test-pol" ])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "1234\n$prompt$"            { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test27
+
+test "modify-principal 28"
+proc test28 {} {
+    global test
+    global prompt
+#    set prms_id 1358
+#    setup_xfail {*-*-*} $prms_id    
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal_pol "$test/a" "test-pol" ])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 999999999 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+       error_and_restart "$test: cannot retrieve policy"
+       return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_mod_date"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_mod_date"
+           return
+       }
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_expire"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_expire"
+           return
+       }
+    }
+    send "lindex \$policy 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_max_life"
+           return
+       }
+    }
+    if { $pw_expire != 999999999 } {
+       fail "$test: pw_expire $pw_expire should be 999999999"
+       return
+    }
+    pass "$test"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test28
+
+test "modify-principal 29"
+proc test29 {} {
+    global test
+    global prompt
+    
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { ! ([create_principal_pol "$test/a" test-pol])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_POLICY_CLR}
+    } $test]]} {
+       fail "$test: modifiy failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test29
+
+test "modify-principal 30"
+proc test30 {} {
+    global test
+    global prompt
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal_pol "$test/a" test-pol])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol-nopw] {KADM5_POLICY}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 3\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test30
+
+test "modify-principal 31"
+proc test31 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol] {KADM5_POLICY}
+    } $test]]} {
+       fail "modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+       error_and_restart "$test: cannot retrieve policy"
+       return
+    }
+    send "lindex \$principal 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_mod_date"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_mod_date"
+           return
+       }
+    }
+
+    send "lindex \$principal 3\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_expire"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_expire"
+           return
+       }
+    }
+
+    send "lindex \$policy 2\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting pw_max_life"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting pw_max_life"
+           return
+       }
+    }
+    if { [expr "$pw_mod_date + $pw_max_life"] != $pw_expire } {
+       fail "$test: pw_expire is wrong"
+       return
+    }
+
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test31
+
+test "modify-principal 32"
+proc test32 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+       error_and_restart "$test: couldn't delete principal \"$test/a\""
+       return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 1234 0 0 0 0 0 0 0 0 0 0} \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 1\n"
+    expect {
+       -re "1234\n$prompt$"            { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test32
+
+test "modify-principal 33"
+proc test33 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_ALL_TIX 0 0 0 0} \
+               {KADM5_ATTRIBUTES}
+    } $test]]} {
+       fail "$test: modified fail"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+       -re "KRB5_KDB_DISALLOW_ALL_TIX.*$prompt$"               { pass "$test" }
+       timeout                                                 { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test33
+
+test "modify-principal 33.25"
+proc test3325 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 0 0 0 0 KRB5_KDB_REQUIRES_PWCHANGE 0 0 0 0} \
+               {KADM5_ATTRIBUTES}
+    } $test]]} {
+       fail "$test: modified fail"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+       -re "KRB5_KDB_REQUIRES_PWCHANGE.*$prompt$"              { pass "$test" }
+       timeout                                                 { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test3325
+
+test "modify-principal 33.5"
+proc test335 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_TGT_BASED 0 0 0 0} \
+               {KADM5_ATTRIBUTES}
+    } $test]]} {
+       fail "$test: modified fail"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 7\n"
+    expect {
+       -re "KRB5_KDB_DISALLOW_TGT_BASED.*$prompt$"             { pass "$test" }
+       timeout                                                 { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test335
+
+
+test "modify-principal 34"
+proc test34 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 0 3456 0 0 0 0 0 0 0} {KADM5_MAX_LIFE}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+       -re "3456\n$prompt$"            { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test34
+
+test "modify-principal 35"
+proc test35 {} {
+    global prompt
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 0 0 0 0 0 7 0 0 0} {KADM5_KVNO}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 8\n"
+    expect {
+       -re "7\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test35
+
+test "modify-principal 36"
+proc test36 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { !( [create_principal_pol "$test/a" "test-pol"])} {
+       error_and_restart "$test: could not create principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol pol}]}  {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               test-pol] {KADM5_POLICY}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 10\n"
+    expect {
+       -re "test-pol\n$prompt$"        { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    send "lindex \$pol 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { ! [cmd {kadm5_get_policy $server_handle test-pol pol2}]} {
+       perror "$test: unexpected failure on get policy"
+       return
+    }
+    send "lindex \$pol2 6\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting principal kvno (second time)"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting principal kvno (second time)"
+           return
+       }
+    }
+    if { $oldref != $newref } {
+       fail "$test: policy reference count is wrong"
+       return;
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test36
+
+test "modify-principal 37"
+proc test37 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if { !( [create_principal "$test/a"])} {
+       error_and_restart "$test: could not create principal \"$test/a\""
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_POLICY_CLR}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test37
+
+test "modify-principal 38"
+proc test38 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 1\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test38
+
+test "modify-principal 39"
+proc test39 {} {
+    global test
+    global prompt
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! ([create_principal "$test/a"])} {
+       perror "$test: unexpected failure in creating principal"
+       return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+               {KADM5_MAX_LIFE}
+    } $test]]} {
+       fail "$test: modify failed"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+    } $test]]} {
+       error_and_restart "$test: could not retrieve principal"
+       return
+    }
+    send "lindex \$principal 4\n"
+    expect {
+       -re "0\n$prompt$"               { pass "$test" }
+       timeout                         { fail "$test" }
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test39
+
+test "modify-principal 40"
+proc test40 {} {
+    global test
+    global prompt
+    
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_modify_principal $server_handle null \
+               {KADM5_PRINC_EXPIRE_TIME}
+    } "EINVAL"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test40
+
+test "modify-principal 43"
+proc test43 {} {
+       global test
+       one_line_fail_test [format {
+           kadm5_modify_principal null [simple_principal \
+                   "%s/a"] {KADM5_PW_EXPIRATION}
+       } $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+test "modify-principal 44"
+proc test44 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    # setting fail auth count to a non-zero value must fail
+    one_line_fail_test [format {
+       kadm5_modify_principal $server_handle \
+               {"%s/a" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1234 0 0 {} {}} {KADM5_FAIL_AUTH_COUNT}
+    } $test] "BAD_SERVER_PARAMS"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test44
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/randkey-principal-v2.exp b/src/lib/kadm5/unit-test/api.3/randkey-principal-v2.exp
new file mode 100644 (file)
index 0000000..ee652cb
--- /dev/null
@@ -0,0 +1,62 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "randkey-principal 100"
+proc test100 {} {
+    global test prompt
+
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal "$test/a"]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+
+    # I'd like to specify a long list of keysalt tuples and make sure
+    # that randkey does the right thing, but we can only use those
+    # enctypes that krbtgt has a key for: des-cbc-crc:normal and
+    # des-cbc-crc:v4, according to the prototype kdc.conf.
+    if {! [cmd [format {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]]} {
+       perror "$test: unexpected failure in randkey_principal"
+    }
+    send "puts \$num_keys\n"
+    expect {
+       -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+       timeout {
+           error_and_restart "$test: timeout getting num_keys"
+           return
+       }
+       eof {
+           error_and_restart "$test: eof getting num_keys"
+           return
+       }
+    }
+
+    # XXX Perhaps I should actually check the key type returned.
+    if {$num_keys == 2} {
+       pass "$test"
+    } else {
+       fail "$test: $num_keys keys, should be 2"
+    }
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test100
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.3/randkey-principal.exp b/src/lib/kadm5/unit-test/api.3/randkey-principal.exp
new file mode 100644 (file)
index 0000000..f003863
--- /dev/null
@@ -0,0 +1,319 @@
+load_lib lib.t
+api_exit
+api_start
+
+test "randkey-principal 1"
+proc test1 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    
+    if {! [cmd [format {
+       kadm5_init "%s/a" "%s/a" $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } $test $test]]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "PASS_TOOSOON"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test1 } 
+
+test "randkey-principal 3"
+proc test3 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    
+    if {! [cmd [format {
+       kadm5_init "%s/a" "%s/a" $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } $test $test]]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "PASS_TOOSOON"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if ${RPC} { test3 } 
+
+test "randkey-principal 13"
+proc test13 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+               once-a-min] KADM5_POLICY
+    } $test]]} {
+       perror "$test: failed modify"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test13
+
+test "randkey-principal 15"
+proc test15 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal_pol "$test/a" once-a-min]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "AUTH_CHANGEPW"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if { $RPC } { test15 }
+
+test "randkey-principal 28"
+proc test28 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test28
+
+test "randkey-principal 28.25"
+proc test2825 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test] "AUTH"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+if {$RPC} { test2825 }
+
+test "randkey-principal 28.5"
+proc test285 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [cmd {
+       kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test285
+
+test "randkey-principal 30"
+proc test30 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't delete principal \"$test/a\""
+           return
+    }
+    if {! [create_principal "$test/a"]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    if {! [cmd [format {
+       kadm5_init "%s/a" "%s/a" $KADM5_CHANGEPW_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } $test $test]]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test30
+
+test "randkey-principal 31"
+proc test31 {} {
+    global test
+    if {! (( ! [principal_exists "$test/a"]) ||
+          [delete_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if {! [create_principal "$test/a"]} {
+       error_and_restart "$test: creating principal"
+       return
+    }
+    
+    if {! [cmd [format {
+       kadm5_init "%s/a" "%s/a" $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    } $test $test]]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_succeed_test [format {
+       kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+    } $test]
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test31
+
+test "randkey-principal 32"
+proc test32 {} {
+    global test
+
+    if { ! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test {
+       kadm5_randkey_principal $server_handle kadmin/history keys num_keys
+    } "PROTECT"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+test32
+
+test "randkey-principal 33"
+proc test33 {} {
+    global test
+    if {! ((  [principal_exists "$test/a"]) ||
+          [create_principal "$test/a"])} {
+           error_and_restart "$test: couldn't create principal \"$test/a\""
+           return
+    }
+    if { ! [cmd {
+       kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+               $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \
+               server_handle
+    }]} {
+       perror "$test: unexpected failure in init"
+       return
+    }
+    one_line_fail_test [format {
+       kadm5_randkey_principal null "%s/a" keys num_keys
+    } $test] "BAD_SERVER_HANDLE"
+    if { ! [cmd {kadm5_destroy $server_handle}]} {
+       perror "$test: unexpected failure in destroy"
+       return
+    }
+}
+
+test33
+
+return ""
index 0bbd72dad541d1a59f1e7ab600d263ffea7a0b09..996e2b0e69c7af05b9c90ea41dd6d18a9a215866 100644 (file)
@@ -157,7 +157,7 @@ proc api_start {} {
                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"}
index e9dd25a3ca9b3066ec9f3801b3a03122c86ed048..9aabb1a86de7b4a1feb3c52520a5261a718c8b1c 100644 (file)
@@ -27,7 +27,7 @@ int main()
      }
      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");
index b5bc82f02cf857050cb9972741c0bb2d72b738e9..6c26e5f0ddc1d7f280b59ba8a89aaced476a5221 100644 (file)
@@ -25,7 +25,7 @@ int main(int argc, char *argv[])
     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");
index 8c7527cb938b04d01637ff3dbc55104f88b1e0c9..cfa79374b6cf772df11630a5eed6c9cdbfb70973 100644 (file)
@@ -20,7 +20,7 @@ int main()
         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);
index e3e0b746ab0156497f23fc80d4938139eff2b919..be154073552324284a6771376a65006b3fb9ae7c 100644 (file)
@@ -22,7 +22,7 @@ int main(int argc, char **argv)
         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");
index 9537fc36aad32dd6d5b520e97f4d6c106d21b187..1cd1e042ade75ecd3c1a36dea69cfb1effdee351 100644 (file)
@@ -19,7 +19,7 @@ proc lib_start_api {} {
        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"
index a9c9d9856ca4d35bb24ea64897a598fb2f0952bd..4e6787a1b2e9615275de07203fe2f82dd5b6645a 100644 (file)
@@ -23,7 +23,7 @@ int main()
 
      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");
index 27bd7b793aeaa518971176841a593df6d1d1f343..1dadfc72ad7068798c85abc31b6d63599df0687c 100644 (file)
@@ -119,7 +119,7 @@ main(int argc, char **argv)
   }
 
   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");
index 840e7a2e58c5b01adf14d9ed5636a59e9399f727..82ffdfe0598ae9732e3a33399dd28d77fe03ced5 100644 (file)
@@ -219,5 +219,11 @@ program KRB5_IPROP_PROG {
                 */
                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;
index cecf5133f1faa204768429d5028087adbe43f271..9eacac3ea7293d19adf7e52a97580e7f224a864f 100644 (file)
@@ -44,6 +44,7 @@ typedef enum {
  */
 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 @@ find_changed_attrs(krb5_db_entry *current, krb5_db_entry *new,
     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 @@ find_changed_attrs(krb5_db_entry *current, krb5_db_entry *new,
                break;
            }
        }
-
     } else {
        attrs[i++] = AT_TL_DATA;
     }
@@ -307,6 +309,8 @@ ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries,
     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 @@ ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries,
        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 @@ ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries,
                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 @@ ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries,
                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 @@ ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries,
                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 @@ ulog_conv_2logentry(krb5_context context, krb5_db_entry *entries,
                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 @@ ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries,
     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 @@ ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries,
     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 @@ ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries,
                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 @@ ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries,
                }
                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 @@ ulog_conv_2dbentry(krb5_context context, krb5_db_entry *entries,
                }
                break;
 /* END CSTYLED */
-
+           }
            case AT_PW_LAST_CHANGE:
                if ((ret = krb5_dbe_update_last_pwd_change(context, ent,
                                                           u.av_pw_last_change)))
index dd3045c168c8ebc435fca10d16e839c2a627e78d..b2532a4fd0541efd19c768fcaee3ba7d10f2913c 100644 (file)
@@ -25,7 +25,7 @@ DB_DEPS-redirect = $(BUILDTOP)/include/db.h
 DB_LIB         = @DB_LIB@
 KDB5_DB_LIB    = @KDB5_DB_LIB@
 DB_DEPLIB      = $(DB_DEPLIB-@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 @@ SHLIB_EXPDEPS = \
        $(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 @@ SRCS= \
        $(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 @@ STLIBOBJS= \
        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
index 85864ac6fe372b80ac739cb02dfc913cf9c1a49d..2e1f3b5198f4253efe741e16c33d5ddd4cb7137f 100644 (file)
@@ -197,6 +197,13 @@ WRAP_K (krb5_db2_promote_db,
        ( 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 @@ kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_db2, kdb_function_table) = {
   /* 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
 };
index a947f2b0371cfd7cb6cd48f6e34ec52a13315da0..b987039d151e1050f4da255a4f4195f2ca2248dc 100644 (file)
@@ -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 @@ destroy_file_suffix(char *dbname, char *suffix)
     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 @@ krb5_db2_open(krb5_context kcontext,
        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 @@ krb5_db2_create(krb5_context kcontext, char *conf_section, char **db_args)
        }
        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_db_set_option(krb5_context kcontext, int option, void *value)
     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_db2_promote_db(krb5_context kcontext, char *conf_section, char **db_args)
     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 @@ krb5_db2_promote_db(krb5_context kcontext, char *conf_section, char **db_args)
        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 @@ clean_n_exit:
     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 @@ clean_n_exit:
  * 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 @@ krb5_db2_db_rename(context, from, to)
      * 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 @@ krb5_db2_db_rename(context, from, to)
     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 @@ krb5_db2_db_rename(context, from, to)
     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 @@ krb5_db2_db_rename(context, from, to)
        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 @@ errout:
 
     return retval;
 }
+
index 640c4d62d3ae61bec439d33952cdf5fc9d0d3d3b..cef7b648a8e27ac3604e0c43f19e2f6c29cea9d4 100644 (file)
@@ -71,7 +71,8 @@ krb5_error_code krb5_db2_db_destroy
 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 @@ void krb5_db2_free_policy( krb5_context kcontext,
 /* 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 */
diff --git a/src/plugins/kdb/db2/kdb_ext.c b/src/plugins/kdb/db2/kdb_ext.c
new file mode 100644 (file)
index 0000000..9d73966
--- /dev/null
@@ -0,0 +1,99 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * plugins/kdb/db2/kdb_ext.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ *
+ */
+
+#include "k5-int.h"
+#include "kdb.h"
+#include <stdio.h>
+#include <errno.h>
+#include <kdb_ext.h>
+#include "kdb_db2.h"
+
+static krb5_error_code
+krb5_db2_check_policy_as(krb5_context context,
+                         unsigned int method,
+                         const krb5_data *request,
+                         krb5_data *response)
+{
+    const kdb_check_policy_as_req *req;
+    kdb_check_policy_as_rep *rep;
+    krb5_error_code code;
+
+    req = (const kdb_check_policy_as_req *)request->data;
+    rep = (kdb_check_policy_as_rep *)response->data;
+
+    rep->status = NULL;
+
+    code = krb5_db2_lockout_check_policy(context, req->client,
+                                         req->kdc_time);
+    if (code == KRB5KDC_ERR_CLIENT_REVOKED)
+        rep->status = "LOCKED_OUT";
+
+    return code;
+}
+
+static krb5_error_code
+krb5_db2_audit_as(krb5_context context,
+                  unsigned int method,
+                  const krb5_data *request,
+                  krb5_data *response)
+{
+    const kdb_audit_as_req *req;
+    krb5_error_code code;
+
+    req = (const kdb_audit_as_req *)request->data;
+
+    code = krb5_db2_lockout_audit(context, req->client,
+                                  req->authtime, req->error_code);
+
+    return code;
+}
+
+krb5_error_code
+krb5_db2_invoke(krb5_context context,
+                unsigned int method,
+                const krb5_data *req,
+                krb5_data *rep)
+{
+    krb5_error_code code = KRB5_KDB_DBTYPE_NOSUP;
+
+    switch (method) {
+    case KRB5_KDB_METHOD_CHECK_POLICY_AS:
+        code = krb5_db2_check_policy_as(context, method, req, rep);
+        break;
+    case KRB5_KDB_METHOD_AUDIT_AS:
+        code = krb5_db2_audit_as(context, method, req, rep);
+        break;
+    default:
+        break;
+    }
+
+    return code;
+}
+
diff --git a/src/plugins/kdb/db2/lockout.c b/src/plugins/kdb/db2/lockout.c
new file mode 100644 (file)
index 0000000..1e6602d
--- /dev/null
@@ -0,0 +1,196 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * plugins/kdb/db2/lockout.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ *
+ */
+
+#include "k5-int.h"
+#include "kdb.h"
+#include <stdio.h>
+#include <errno.h>
+#include <kadm5/server_internal.h>
+#include "kdb_db2.h"
+
+/*
+ * Helper routines for databases that wish to use the default
+ * principal lockout functionality.
+ */
+
+static krb5_error_code
+lookup_lockout_policy(krb5_context context,
+                      krb5_db_entry *entry,
+                      krb5_kvno *pw_max_fail,
+                      krb5_deltat *pw_failcnt_interval,
+                      krb5_deltat *pw_lockout_duration)
+{
+    krb5_tl_data tl_data;
+    krb5_error_code code;
+    osa_princ_ent_rec adb;
+    XDR xdrs;
+
+    *pw_max_fail = 0;
+    *pw_failcnt_interval = 0;
+    *pw_lockout_duration = 0;
+
+    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+
+    code = krb5_dbe_lookup_tl_data(context, entry, &tl_data);
+    if (code != 0 || tl_data.tl_data_length == 0)
+        return code;
+
+    memset(&adb, 0, sizeof(adb));
+    xdrmem_create(&xdrs, (char *)tl_data.tl_data_contents,
+                  tl_data.tl_data_length, XDR_DECODE);
+    if (!xdr_osa_princ_ent_rec(&xdrs, &adb)) {
+        xdr_destroy(&xdrs);
+        return KADM5_XDR_FAILURE;
+    }
+
+    if (adb.policy != NULL) {
+        osa_policy_ent_t policy = NULL;
+        int count = 0;
+
+        code = krb5_db2_get_policy(context, adb.policy,
+                                   &policy, &count);
+        if (code == 0 && count == 1) {
+            *pw_max_fail = policy->pw_max_fail;
+            *pw_failcnt_interval = policy->pw_failcnt_interval;
+            *pw_lockout_duration = policy->pw_lockout_duration;
+        }
+        if (policy != NULL)
+            krb5_db2_free_policy(context, policy);
+    }
+
+    xdr_destroy(&xdrs);
+
+    xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+    xdr_osa_princ_ent_rec(&xdrs, &adb);
+    xdr_destroy(&xdrs);
+
+    return 0;
+}
+
+/* draft-behera-ldap-password-policy-10.txt 7.1 */
+static krb5_boolean
+locked_check_p(krb5_context context,
+               krb5_timestamp stamp,
+               krb5_kvno max_fail,
+               krb5_timestamp lockout_duration,
+               krb5_db_entry *entry)
+{
+    if (max_fail == 0 || entry->fail_auth_count < max_fail)
+        return FALSE;
+
+    if (lockout_duration == 0)
+        return TRUE; /* principal permanently locked */
+
+    return (stamp < entry->last_failed + lockout_duration);
+}
+
+krb5_error_code
+krb5_db2_lockout_check_policy(krb5_context context,
+                              krb5_db_entry *entry,
+                              krb5_timestamp stamp)
+{
+    krb5_error_code code;
+    krb5_kvno max_fail = 0;
+    krb5_deltat failcnt_interval = 0;
+    krb5_deltat lockout_duration = 0;
+
+    code = lookup_lockout_policy(context, entry, &max_fail,
+                                 &failcnt_interval,
+                                 &lockout_duration);
+    if (code != 0)
+        return code;
+
+    if (locked_check_p(context, stamp, max_fail, lockout_duration, entry))
+        return KRB5KDC_ERR_CLIENT_REVOKED;
+
+    return 0;
+}
+
+krb5_error_code
+krb5_db2_lockout_audit(krb5_context context,
+                       krb5_db_entry *entry,
+                       krb5_timestamp stamp,
+                       krb5_error_code status)
+{
+    krb5_error_code code;
+    krb5_kvno max_fail = 0;
+    krb5_deltat failcnt_interval = 0;
+    krb5_deltat lockout_duration = 0;
+    int nentries = 1;
+
+    switch (status) {
+    case 0:
+    case KRB5KDC_ERR_PREAUTH_FAILED:
+    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+        break;
+#if 0
+    case KRB5KDC_ERR_CLIENT_REVOKED:
+        break;
+#endif
+    default:
+        return 0;
+    }
+
+    code = lookup_lockout_policy(context, entry, &max_fail,
+                                 &failcnt_interval,
+                                 &lockout_duration);
+    if (code != 0)
+        return code;
+
+    assert (!locked_check_p(context, stamp, max_fail, lockout_duration, entry));
+
+    if (status == 0 && (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)) {
+        /*
+         * Only mark the authentication as successful if the entry
+         * required preauthentication, otherwise we have no idea.
+         */
+        entry->fail_auth_count = 0;
+        entry->last_success = stamp;
+    } else if (status == KRB5KDC_ERR_PREAUTH_FAILED ||
+               status == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+        if (failcnt_interval != 0 &&
+            stamp > entry->last_failed + failcnt_interval) {
+            /* Reset fail_auth_count after failcnt_interval */
+            entry->fail_auth_count = 0;
+        }
+
+        entry->last_failed = stamp;
+        entry->fail_auth_count++;
+    } else
+        return 0; /* nothing to do */
+
+    code = krb5_db2_db_put_principal(context, entry,
+                                     &nentries, NULL);
+    if (code != 0)
+        return code;
+
+    return 0;
+}
+
index 82e29b804634c0d99322770f38e54129a59119a7..31856fbd2a8373848ebd86ea02c3d4f937c541ec 100644 (file)
@@ -51,14 +51,27 @@ bool_t xdr_nullstring(XDR *xdrs, char **objp)
      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 @@ xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp)
     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 @@ xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp)
        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);
 }
index 11fece3df2a453d03c49a405cfdbbd601c75ecf4..d841d7376fa33c16f84ecb2150514b8729e31390 100644 (file)
@@ -39,6 +39,7 @@ typedef       long            osa_adb_ret_t;
 
 #define OSA_ADB_POLICY_VERSION_MASK    0x12345D00
 #define OSA_ADB_POLICY_VERSION_1       0x12345D01
+#define OSA_ADB_POLICY_VERSION_2       0x12345D02
 
 
 
index 18a89fd6197e3143abed8d57fd15eb5ca65f7965..742e3ce5072396c1eea925a118c487a588a09d9f 100644 (file)
@@ -87,6 +87,10 @@ kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_ldap, kdb_function_table) = {
   /* 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,
 
 };
index 8479fb6fcbfa1cb4f49f0cbd02a7495c8b0bcded..4306da102d55e861c8fa73eebc415416f5cea0df 100644 (file)
@@ -54,8 +54,10 @@ SRCS=        $(srcdir)/kdb_ldap.c \
        $(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 @@ STLIBOBJS= kdb_ldap.o \
        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
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c
new file mode 100644 (file)
index 0000000..0009b59
--- /dev/null
@@ -0,0 +1,99 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * plugins/kdb/ldap/kdb_ext.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ *
+ */
+
+#include "k5-int.h"
+#include "kdb.h"
+#include <stdio.h>
+#include <errno.h>
+#include <kdb_ext.h>
+#include "kdb_ldap.h"
+
+static krb5_error_code
+krb5_ldap_check_policy_as(krb5_context context,
+                          unsigned int method,
+                          const krb5_data *request,
+                          krb5_data *response)
+{
+    const kdb_check_policy_as_req *req;
+    kdb_check_policy_as_rep *rep;
+    krb5_error_code code;
+
+    req = (const kdb_check_policy_as_req *)request->data;
+    rep = (kdb_check_policy_as_rep *)response->data;
+
+    rep->status = NULL;
+
+    code = krb5_ldap_lockout_check_policy(context, req->client,
+                                          req->kdc_time);
+    if (code == KRB5KDC_ERR_CLIENT_REVOKED)
+        rep->status = "LOCKED_OUT";
+
+    return code;
+}
+
+static krb5_error_code
+krb5_ldap_audit_as(krb5_context context,
+                   unsigned int method,
+                   const krb5_data *request,
+                   krb5_data *response)
+{
+    const kdb_audit_as_req *req;
+    krb5_error_code code;
+
+    req = (const kdb_audit_as_req *)request->data;
+
+    code = krb5_ldap_lockout_audit(context, req->client,
+                                   req->authtime, req->error_code);
+
+    return code;
+}
+
+krb5_error_code
+krb5_ldap_invoke(krb5_context context,
+                 unsigned int method,
+                 const krb5_data *req,
+                 krb5_data *rep)
+{
+    krb5_error_code code = KRB5_KDB_DBTYPE_NOSUP;
+
+    switch (method) {
+    case KRB5_KDB_METHOD_CHECK_POLICY_AS:
+        code = krb5_ldap_check_policy_as(context, method, req, rep);
+        break;
+    case KRB5_KDB_METHOD_AUDIT_AS:
+        code = krb5_ldap_audit_as(context, method, req, rep);
+        break;
+    default:
+        break;
+    }
+
+    return code;
+}
+
index 4b8fcb2b5d1d721c41add7c48f7b209ace2ee1c9..0d86801d649cab4aa4a846e3155cc8efa6dec3e0 100644 (file)
@@ -162,69 +162,68 @@ cleanup:
 }
 
 
-/* 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 @@ cleanup:
     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);
index 802ab0fc36ae3611ef1b6fb5def329a0903a8631..d14b48bf9793ec13f07a39790f1b6d8edf91447b 100644 (file)
@@ -197,6 +197,7 @@ struct _krb5_ldap_server_info {
 #ifdef HAVE_EDIRECTORY
     char                       *root_certificate_file;
 #endif
+    int                                 modify_increment;
     struct _krb5_ldap_server_info *next;
 };
 
@@ -291,6 +292,9 @@ krb5_ldap_read_startup_information(krb5_context );
 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 @@ int
 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
index fdc5d10c771738116097bf94a3bbbcc0a93a24c3..db1f76a69e22b6bdeaac1ec04df765e1f6929c9a 100644 (file)
@@ -229,6 +229,13 @@ krb5_ldap_db_init(krb5_context context, krb5_ldap_context *ldap_context)
 
            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;
index 0bbdcf878306aef73a18eb486967c71c0bd92b3d..fd226b13d38c3abef3749181e691bcdc54b1a592 100644 (file)
@@ -337,6 +337,42 @@ attributetypes: ( 2.16.840.1.113719.1.301.4.34.1
                 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 @@ objectClasses: ( 2.16.840.1.113719.1.301.6.14.1
                 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.
index 9352cf1e46e4dadabc324f7c5d6b0e2fe94d57c5..9525e60d6284b0bb76180400041550a6bf6feafe 100644 (file)
@@ -270,6 +270,33 @@ attributetype ( 2.16.840.1.113719.1.301.4.34.1
                 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 @@ attributetype ( 2.16.840.1.113719.1.301.4.53.1
                 EQUALITY distinguishedNameMatch
                 SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
 
-
 ########################################################################
 ########################################################################
 #                      Object Class Definitions                       #
@@ -616,7 +642,7 @@ objectclass ( 2.16.840.1.113719.1.301.6.14.1
                 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.
index 502e71ccd559fa45685b06c0e8c80540c56903b8..abc27f1148d00415b983aac4ef405b2c27993426 100644 (file)
 #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[];
 
index 03c3da48d78b78ec23872394f38b29aae781d91a..f81d399041dded0942646aa147cce99388815b0f 100644 (file)
@@ -863,7 +863,7 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
            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 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
            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 @@ krb5_ldap_put_principal(context, entries, nentries, db_args)
            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_ldap_put_principal(context, entries, nentries, db_args)
                krb5_set_error_message(context, st, "%s", errbuf);
                goto cleanup;
            }
+
+           if (entries->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT)
+               entries->fail_auth_count++;
        }
     }
 
index 94d461b29fbce49ecb84d58589d0323232685d7e..ed63e0812e15ca2625c3cd2b5ba0b065671d9b34 100644 (file)
@@ -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 @@ krb5_ldap_create_password_policy (context, policy)
        || ((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 @@ krb5_ldap_put_password_policy (context, policy)
        || ((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 @@ populate_policy(krb5_context context,
     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",
index 23bb3dbeb27a71483b810e9148776f092665d9fb..d670f59fb72013d8ed376e6230edb4a10618c69f 100644 (file)
@@ -87,6 +87,9 @@ static char *adminrights_subtree[][2]={
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"6#subtree#","#krbPwdMaxFailure"},
+    {"6#subtree#","#krbPwdFailureCountInterval"},
+    {"6#subtree#","#krbPwdLockoutDuration"},
     { "","" }
 };
 
@@ -116,6 +119,9 @@ static char *pwdrights_subtree[][2] = {
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"2#subtree#","#krbPwdMaxFailure"},
+    {"2#subtree#","#krbPwdFailureCountInterval"},
+    {"2#subtree#","#krbPwdLockoutDuration"},
     { "", "" }
 };
 
@@ -187,6 +193,9 @@ static char *adminrights_realmcontainer[][2]={
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"6#subtree#","#krbPwdMaxFailure"},
+    {"6#subtree#","#krbPwdFailureCountInterval"},
+    {"6#subtree#","#krbPwdLockoutDuration"},
     { "","" }
 };
 
@@ -225,6 +234,9 @@ static char *pwdrights_realmcontainer[][2]={
     {"2#subtree#","#krbLastFailedAuth"},
     {"2#subtree#","#krbLoginFailedCount"},
     {"2#subtree#","#krbLastSuccessfulAuth"},
+    {"2#subtree#","#krbPwdMaxFailure"},
+    {"2#subtree#","#krbPwdFailureCountInterval"},
+    {"2#subtree#","#krbPwdLockoutDuration"},
     { "", "" }
 };
 
index a0d94f67407a1238ab01efc389c8fc1d84cb30c6..1ec9a39070719651f54283a8e81388610a81bcca 100644 (file)
@@ -51,3 +51,4 @@ krb5_ldap_release_errcode_string
 krb5_ldap_create
 krb5_ldap_set_mkey_list
 krb5_ldap_get_mkey_list
+krb5_ldap_invoke
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/lockout.c b/src/plugins/kdb/ldap/libkdb_ldap/lockout.c
new file mode 100644 (file)
index 0000000..6b2d49e
--- /dev/null
@@ -0,0 +1,192 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * plugins/kdb/ldap/lockout.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include <kdb.h>
+
+#include "kdb_ldap.h"
+#include "princ_xdr.h"
+#include "ldap_principal.h"
+#include "ldap_pwd_policy.h"
+#include "ldap_tkt_policy.h"
+
+static krb5_error_code
+lookup_lockout_policy(krb5_context context,
+                      krb5_db_entry *entry,
+                      krb5_kvno *pw_max_fail,
+                      krb5_deltat *pw_failcnt_interval,
+                      krb5_deltat *pw_lockout_duration)
+{
+    krb5_tl_data tl_data;
+    krb5_error_code code;
+    osa_princ_ent_rec adb;
+    XDR xdrs;
+
+    *pw_max_fail = 0;
+    *pw_failcnt_interval = 0;
+    *pw_lockout_duration = 0;
+
+    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+
+    code = krb5_dbe_lookup_tl_data(context, entry, &tl_data);
+    if (code != 0 || tl_data.tl_data_length == 0)
+        return code;
+
+    memset(&adb, 0, sizeof(adb));
+
+    code = krb5_lookup_tl_kadm_data(&tl_data, &adb);
+    if (code != 0)
+        return code;
+
+    if (adb.policy != NULL) {
+        osa_policy_ent_t policy = NULL;
+        int count = 0;
+
+        code = krb5_ldap_get_password_policy(context, adb.policy,
+                                             &policy, &count);
+        if (code == 0 && count == 1) {
+            *pw_max_fail = policy->pw_max_fail;
+            *pw_failcnt_interval = policy->pw_failcnt_interval;
+            *pw_lockout_duration = policy->pw_lockout_duration;
+        }
+        krb5_ldap_free_password_policy(context, policy);
+    }
+
+    xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+    ldap_xdr_osa_princ_ent_rec(&xdrs, &adb);
+    xdr_destroy(&xdrs);
+
+    return 0;
+}
+
+/* draft-behera-ldap-password-policy-10.txt 7.1 */
+static krb5_boolean
+locked_check_p(krb5_context context,
+               krb5_timestamp stamp,
+               krb5_kvno max_fail,
+               krb5_timestamp lockout_duration,
+               krb5_db_entry *entry)
+{
+    if (max_fail == 0 || entry->fail_auth_count < max_fail)
+        return FALSE;
+
+    if (lockout_duration == 0)
+        return TRUE; /* principal permanently locked */
+
+    return (stamp < entry->last_failed + lockout_duration);
+}
+
+krb5_error_code
+krb5_ldap_lockout_check_policy(krb5_context context,
+                               krb5_db_entry *entry,
+                               krb5_timestamp stamp)
+{
+    krb5_error_code code;
+    krb5_kvno max_fail = 0;
+    krb5_deltat failcnt_interval = 0;
+    krb5_deltat lockout_duration = 0;
+
+    code = lookup_lockout_policy(context, entry, &max_fail,
+                                 &failcnt_interval,
+                                 &lockout_duration);
+    if (code != 0 || failcnt_interval == 0)
+        return code;
+
+    if (locked_check_p(context, stamp, max_fail, lockout_duration, entry))
+        return KRB5KDC_ERR_CLIENT_REVOKED;
+
+    return 0;
+}
+
+krb5_error_code
+krb5_ldap_lockout_audit(krb5_context context,
+                        krb5_db_entry *entry,
+                        krb5_timestamp stamp,
+                        krb5_error_code status)
+{
+    krb5_error_code code;
+    krb5_kvno max_fail = 0;
+    krb5_deltat failcnt_interval = 0;
+    krb5_deltat lockout_duration = 0;
+    int nentries = 1;
+
+    switch (status) {
+    case 0:
+    case KRB5KDC_ERR_PREAUTH_FAILED:
+    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+        break;
+    default:
+        return 0;
+    }
+
+    code = lookup_lockout_policy(context, entry, &max_fail,
+                                 &failcnt_interval,
+                                 &lockout_duration);
+    if (code != 0)
+        return code;
+
+    entry->mask = 0;
+
+    assert (!locked_check_p(context, stamp, max_fail, lockout_duration, entry));
+
+    if (status == 0 && (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)) {
+        /*
+         * Only mark the authentication as successful if the entry
+         * required preauthentication, otherwise we have no idea.
+         */
+        entry->fail_auth_count = 0;
+        entry->last_success = stamp;
+        entry->mask |= KADM5_FAIL_AUTH_COUNT | KADM5_LAST_SUCCESS;
+    } else if (status == KRB5KDC_ERR_PREAUTH_FAILED ||
+               status == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+        if (failcnt_interval != 0 &&
+            stamp > entry->last_failed + failcnt_interval) {
+            /* Reset fail_auth_count after failcnt_interval */
+            entry->fail_auth_count = 0;
+            entry->mask |= KADM5_FAIL_AUTH_COUNT;
+        }
+
+        entry->last_failed = stamp;
+        entry->mask |= KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT_INCREMENT;
+    }
+
+    if (entry->mask) {
+        code = krb5_ldap_put_principal(context, entry,
+                                       &nentries, NULL);
+        if (code != 0)
+            return code;
+    }
+
+    return 0;
+}
index 41a940725b61043121a396d463fad4a372362d6a..c9841e2f82e6ac210430cb39fc951f3aa80bf79c 100644 (file)
@@ -190,7 +190,7 @@ unsigned int backoff_from_master(int *);
 
 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 @@ void doit(fd)
        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 @@ krb5_error_code do_iprop(kdb_log_context *log_ctx)
        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 @@ reinit:
                                      master_svc_princstr,
                                      &params,
                                      KADM5_STRUCT_VERSION,
-                                     KADM5_API_VERSION_2,
+                                     KADM5_API_VERSION_3,
                                      db_args,
                                      &server_handle);
 
@@ -788,10 +817,7 @@ reinit:
                                                == 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 @@ reinit:
                                             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 @@ load_database(context, kdb_util, database_file_name)
                        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 @@ load_database(context, kdb_util, database_file_name)
  */
 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;
index a4da274ff538e5127b74d8ec307aaaca5d3e2780..4497072cc525a85f390113aa4f383149d85c8b43 100644 (file)
@@ -23,7 +23,7 @@ if [ "`ls -t $DUMPFILE.dump_ok $KDB_FILE | sed -n 1p`"  = "$KDB_FILE" -o \
 then
 
        date
-       $KDB5_EDIT dump $DUMPFILE > /dev/null
+       $KDB5_UTIL dump $DUMPFILE > /dev/null
 
        $KPROP -d -f $DUMPFILE ${SLAVE}
        rm $DUMPFILE