diff options
| author | Greg Hudson <ghudson@mit.edu> | 2009-10-25 16:55:12 +0000 |
|---|---|---|
| committer | Greg Hudson <ghudson@mit.edu> | 2009-10-25 16:55:12 +0000 |
| commit | 8d31a9d396f5bea88def4db395ad12dca2ac2e9f (patch) | |
| tree | 244f8f5b525432a2a2a280403f38d7b2fbdc0dfd /src/kadmin | |
| parent | b82e46df9b6cbf663512985a99c6d79f2b0cb796 (diff) | |
| download | krb5-8d31a9d396f5bea88def4db395ad12dca2ac2e9f.tar.gz krb5-8d31a9d396f5bea88def4db395ad12dca2ac2e9f.tar.xz krb5-8d31a9d396f5bea88def4db395ad12dca2ac2e9f.zip | |
Account lockout
Merge Luke's users/lhoward/lockout2 branch to trunk. Implements
account lockout policies for preauth-using principals using existing
principal metadata fields and new policy fields. The kadmin API
version is bumped from 2 to 3 to compatibly extend the policy_ent_rec
structure.
ticket: 6577
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23038 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kadmin')
| -rw-r--r-- | src/kadmin/cli/kadmin.c | 55 | ||||
| -rw-r--r-- | src/kadmin/dbutil/dump.c | 285 | ||||
| -rw-r--r-- | src/kadmin/dbutil/kadm5_create.c | 2 | ||||
| -rw-r--r-- | src/kadmin/dbutil/kdb5_util.M | 9 | ||||
| -rw-r--r-- | src/kadmin/dbutil/kdb5_util.c | 4 | ||||
| -rw-r--r-- | src/kadmin/server/ipropd_svc.c | 37 | ||||
| -rw-r--r-- | src/kadmin/server/ovsec_kadmd.c | 2 | ||||
| -rw-r--r-- | src/kadmin/server/server_stubs.c | 4 | ||||
| -rwxr-xr-x | src/kadmin/testing/scripts/init_db | 10 | ||||
| -rwxr-xr-x | src/kadmin/testing/scripts/start_servers_local | 2 | ||||
| -rw-r--r-- | src/kadmin/testing/tcl/util.t | 2 | ||||
| -rw-r--r-- | src/kadmin/testing/util/tcl_kadm5.c | 47 |
12 files changed, 375 insertions, 84 deletions
diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c index ad9f6bc9bd..51746def44 100644 --- a/src/kadmin/cli/kadmin.c +++ b/src/kadmin/cli/kadmin.c @@ -486,7 +486,7 @@ kadmin_startup(int argc, char *argv[]) princstr); retval = kadm5_init_with_creds(context, princstr, cc, svcname, ¶ms, 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, ¶ms, 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, ¶ms, 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); } diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c index 8dab4605ce..c03e88d123 100644 --- a/src/kadmin/dbutil/dump.c +++ b/src/kadmin/dbutil/dump.c @@ -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; @@ -2176,15 +2284,51 @@ process_ov_record(fname, kcontext, filep, verbose, linenop) } /* + * 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); /* diff --git a/src/kadmin/dbutil/kadm5_create.c b/src/kadmin/dbutil/kadm5_create.c index c2196e54b4..a232babd16 100644 --- a/src/kadmin/dbutil/kadm5_create.c +++ b/src/kadmin/dbutil/kadm5_create.c @@ -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"); diff --git a/src/kadmin/dbutil/kdb5_util.M b/src/kadmin/dbutil/kdb5_util.M index f566781ebd..33ab01aa18 100644 --- a/src/kadmin/dbutil/kdb5_util.M +++ b/src/kadmin/dbutil/kdb5_util.M @@ -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. diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c index 1b0d5a492e..a4b2e686d0 100644 --- a/src/kadmin/dbutil/kdb5_util.c +++ b/src/kadmin/dbutil/kdb5_util.c @@ -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" diff --git a/src/kadmin/server/ipropd_svc.c b/src/kadmin/server/ipropd_svc.c index 9140bbdc4c..127a5045d2 100644 --- a/src/kadmin/server/ipropd_svc.c +++ b/src/kadmin/server/ipropd_svc.c @@ -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)"), diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c index fb42c7bde2..c01cbef73a 100644 --- a/src/kadmin/server/ovsec_kadmd.c +++ b/src/kadmin/server/ovsec_kadmd.c @@ -306,7 +306,7 @@ int main(int argc, char *argv[]) if((ret = kadm5_init(context, "kadmind", NULL, NULL, ¶ms, 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); diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c index dc949ff18b..9449fe8c22 100644 --- a/src/kadmin/server/server_stubs.c +++ b/src/kadmin/server/server_stubs.c @@ -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); diff --git a/src/kadmin/testing/scripts/init_db b/src/kadmin/testing/scripts/init_db index 1cb96f843c..d5930223da 100755 --- a/src/kadmin/testing/scripts/init_db +++ b/src/kadmin/testing/scripts/init_db @@ -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}} diff --git a/src/kadmin/testing/scripts/start_servers_local b/src/kadmin/testing/scripts/start_servers_local index 8cd0f3a61d..a8890d7318 100755 --- a/src/kadmin/testing/scripts/start_servers_local +++ b/src/kadmin/testing/scripts/start_servers_local @@ -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] diff --git a/src/kadmin/testing/tcl/util.t b/src/kadmin/testing/tcl/util.t index 0e39061f77..7721609902 100644 --- a/src/kadmin/testing/tcl/util.t +++ b/src/kadmin/testing/tcl/util.t @@ -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} { diff --git a/src/kadmin/testing/util/tcl_kadm5.c b/src/kadmin/testing/util/tcl_kadm5.c index 6679ce0a7c..08f3a52a4d 100644 --- a/src/kadmin/testing/util/tcl_kadm5.c +++ b/src/kadmin/testing/util/tcl_kadm5.c @@ -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); |
