diff options
Diffstat (limited to 'src/kadmin/dbutil/dump.c')
-rw-r--r-- | src/kadmin/dbutil/dump.c | 316 |
1 files changed, 258 insertions, 58 deletions
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c index 2d817df26..e421e7659 100644 --- a/src/kadmin/dbutil/dump.c +++ b/src/kadmin/dbutil/dump.c @@ -49,6 +49,10 @@ krb5_kvno new_mkvno; static int backwards; static int recursive; +#define K5Q1(x) #x +#define K5Q(x) K5Q1(x) +#define K5CONST_WIDTH_SCANF_STR(x) "%" K5Q(x) "s" + /* * Use compile(3) if no regcomp present. */ @@ -94,6 +98,7 @@ static krb5_error_code dump_ov_princ (krb5_pointer, krb5_db_entry *); static void dump_k5beta7_policy (void *, osa_policy_ent_t); static void dump_r1_8_policy (void *, osa_policy_ent_t); +static void dump_r1_11_policy (void *, osa_policy_ent_t); typedef krb5_error_code (*dump_func)(krb5_pointer, krb5_db_entry *); @@ -106,6 +111,8 @@ 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_r1_11_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, @@ -185,14 +192,23 @@ dump_version r1_8_version = { dump_r1_8_policy, process_r1_8_record, }; +dump_version r1_11_version = { + "Kerberos version 5 release 1.11", + "kdb5_util load_dump version 7\n", + 0, + 0, + dump_k5beta7_princ_withpolicy, + dump_r1_11_policy, + process_r1_11_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, + dump_r1_11_policy, + process_r1_11_record, }; /* External data */ @@ -222,6 +238,7 @@ static const char null_mprinc_name[] = "kdb5_dump@MISSING"; #define trash_end_fmt _("%s(%d): ignoring trash at end of line: ") #define read_nomem _("entry (out of memory)") #define read_header _("dump entry header") +#define read_negint _("dump entry (unexpected negative numeric field)") #define read_name_string _("name string") #define read_key_type _("key type") #define read_key_data _("key data") @@ -269,6 +286,7 @@ static const char updateoption[] = "-update"; static const char hashoption[] = "-hash"; static const char ovoption[] = "-ov"; static const char r13option[] = "-r13"; +static const char r18option[] = "-r18"; static const char dump_tmptrail[] = "~"; /* @@ -700,6 +718,33 @@ dump_k5beta6_iterator(ptr, entry) return dump_k5beta6_iterator_ext(ptr, entry, 0); } +/* + * Dumps TL data; common to principals and policies. + * + * If filter_kadm then the KRB5_TL_KADM_DATA (where a principal's policy + * name is stored) is filtered out. This is for dump formats that don't + * support policies. + */ +static void +dump_tl_data(FILE *ofile, krb5_tl_data *tlp, krb5_boolean filter_kadm) +{ + int i; + + for (; tlp; tlp = tlp->tl_data_next) { + if (tlp->tl_data_type == KRB5_TL_KADM_DATA && filter_kadm) + continue; + fprintf(ofile, "\t%d\t%d\t", + (int) tlp->tl_data_type, + (int) tlp->tl_data_length); + if (tlp->tl_data_length) { + for (i = 0; i < tlp->tl_data_length; i++) + fprintf(ofile, "%02x", tlp->tl_data_contents[i]); + } else { + fprintf(ofile, "%d", -1); + } + } +} + static krb5_error_code dump_k5beta6_iterator_ext(ptr, entry, kadm) krb5_pointer ptr; @@ -795,7 +840,7 @@ dump_k5beta6_iterator_ext(ptr, entry, kadm) (int) entry->n_key_data, (int) entry->e_length, name); - fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", + fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d", entry->attributes, entry->max_life, entry->max_renewable_life, @@ -804,21 +849,10 @@ dump_k5beta6_iterator_ext(ptr, entry, kadm) (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) - continue; /* see above, [krb5-admin/89] */ - fprintf(arg->ofile, "%d\t%d\t", - (int) tlp->tl_data_type, - (int) tlp->tl_data_length); - if (tlp->tl_data_length) - for (i=0; i<tlp->tl_data_length; i++) - fprintf(arg->ofile, "%02x", tlp->tl_data_contents[i]); - else - fprintf(arg->ofile, "%d", -1); - fprintf(arg->ofile, "\t"); - } + /* Pound out tagged data. */ + dump_tl_data(arg->ofile, entry->tl_data, !kadm); + fprintf(arg->ofile, "\t"); /* Pound out key data */ for (counter=0; counter<entry->n_key_data; counter++) { @@ -950,6 +984,28 @@ void dump_r1_8_policy(void *data, osa_policy_ent_t entry) entry->pw_failcnt_interval, entry->pw_lockout_duration); } +void +dump_r1_11_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\t" + "%d\t%d\t%d\t%s\t%d", + 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, + entry->attributes, entry->max_life, entry->max_renewable_life, + entry->allowed_keysalts ? entry->allowed_keysalts : "-", + entry->n_tl_data); + + dump_tl_data(arg->ofile, entry->tl_data, FALSE); + fprintf(arg->ofile, "\n"); +} + static void print_key_data(FILE *f, krb5_key_data *key_data) { int c; @@ -1060,9 +1116,9 @@ static krb5_error_code dump_ov_princ(krb5_pointer ptr, krb5_db_entry *kdb) /* * usage is: - * dump_db [-old] [-b6] [-b7] [-ov] [-r13] [-verbose] [-mkey_convert] - * [-new_mkey_file mkey_file] [-rev] [-recurse] - * [filename [principals...]] + * dump_db [-old] [-b6] [-b7] [-ov] [-r13] [-r18] [-verbose] + * [-mkey_convert] [-new_mkey_file mkey_file] [-rev] + * [-recurse] [filename [principals...]] */ void dump_db(argc, argv) @@ -1085,7 +1141,7 @@ dump_db(argc, argv) * Parse the arguments. */ ofile = (char *) NULL; - dump = &r1_8_version; + dump = &r1_11_version; arglist.flags = 0; new_mkey_file = 0; mkey_convert = 0; @@ -1107,6 +1163,8 @@ dump_db(argc, argv) dump = &ov_version; else if (!strcmp(argv[aindex], r13option)) dump = &r1_3_version; + else if (!strcmp(argv[aindex], r18option)) + dump = &r1_8_version; else if (!strncmp(argv[aindex], ipropoption, sizeof(ipropoption) - 1)) { if (log_ctx && log_ctx->iproprole) { /* Note: ipropx_version is the maximum version acceptable */ @@ -1792,6 +1850,65 @@ process_k5beta_record(fname, kcontext, filep, flags, linenop) return(retval); } +/* Allocate and form a TL data list of a desired size. */ +static int +alloc_tl_data(krb5_int16 n_tl_data, krb5_tl_data **tldp) +{ + krb5_tl_data **tlp = tldp; + int i; + + for (i = 0; i < n_tl_data; i++) { + *tlp = calloc(1, sizeof(krb5_tl_data)); + if (*tlp == NULL) + return ENOMEM; /* caller cleans up */ + tlp = &((*tlp)->tl_data_next); + } + + return 0; +} + +/* Read TL data; common to principals and policies */ +static int +process_tl_data(const char *fname, FILE *filep, krb5_tl_data *tl_data, + const char **errstr) +{ + krb5_tl_data *tl; + int nread; + krb5_int32 t1, t2; + + for (tl = tl_data; tl; tl = tl->tl_data_next) { + nread = fscanf(filep, "%d\t%d\t", &t1, &t2); + if (nread != 2) { + *errstr = read_ttypelen; + return EINVAL; + } + if (t2 < 0) { + *errstr = read_negint; + return EINVAL; + } + tl->tl_data_type = (krb5_int16) t1; + tl->tl_data_length = (krb5_int16) t2; + if (tl->tl_data_length) { + tl->tl_data_contents = malloc(t2 + 1); + if (tl->tl_data_contents == NULL) + return ENOMEM; + if (read_octet_string(filep, tl->tl_data_contents, + tl->tl_data_length)) { + *errstr = read_tcontents; + return EINVAL; + } + } else { + nread = fscanf(filep, "%d", &t1); + if (nread != 1 || t1 != -1) { + *errstr = read_tcontents; + return EINVAL; + } + } + } + + return 0; +} + /* * process_k5beta6_record() - Handle a dump record in krb5b6 format. * @@ -1805,11 +1922,10 @@ process_k5beta6_record(char *fname, krb5_context kcontext, FILE *filep, krb5_db_entry *dbentry; krb5_int32 t1, t2, t3, t4, t5, t6, t7, t8, t9; int nread; - int error = 1; int i, j; char *name; krb5_key_data *kp, *kdatap; - krb5_tl_data **tlp, *tl; + krb5_tl_data *tl; krb5_octet *op; krb5_error_code kret; const char *try2read = read_header; @@ -1824,7 +1940,6 @@ process_k5beta6_record(char *fname, krb5_context kcontext, FILE *filep, op = NULL; nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t", &t1, &t2, &t3, &t4, &t5); if (nread == EOF) { - error = 0; retval = -1; goto cleanup; } @@ -1836,14 +1951,9 @@ process_k5beta6_record(char *fname, krb5_context kcontext, FILE *filep, goto cleanup; /* Get memory for and form tagged data linked list */ - tlp = &dbentry->tl_data; - for (i = 0; i < t3; i++) { - if (!(*tlp = malloc(sizeof(krb5_tl_data)))) - goto cleanup; - memset(*tlp, 0, sizeof(krb5_tl_data)); - tlp = &((*tlp)->tl_data_next); - dbentry->n_tl_data++; - } + if (alloc_tl_data(t3, &dbentry->tl_data)) + goto cleanup; + dbentry->n_tl_data = t3; /* Get memory for key list */ if (t4 && (kp = malloc(t4*sizeof(krb5_key_data))) == NULL) @@ -1911,31 +2021,11 @@ process_k5beta6_record(char *fname, krb5_context kcontext, FILE *filep, * that's what I did. [krb5-admin/89] */ if (dbentry->n_tl_data) { + if (process_tl_data(fname, filep, dbentry->tl_data, &try2read)) + goto cleanup; for (tl = dbentry->tl_data; tl; tl = tl->tl_data_next) { - nread = fscanf(filep, "%d\t%d\t", &t1, &t2); - if (nread != 2) { - try2read = read_ttypelen; - goto cleanup; - } - tl->tl_data_type = (krb5_int16) t1; - tl->tl_data_length = (krb5_int16) t2; - if (!tl->tl_data_length) { - /* Should be a null field */ - nread = fscanf(filep, "%d", &t9); - if ((nread != 1) || (t9 != -1)) { - try2read = read_tcontents; - goto cleanup; - } - continue; - } - if (!(tl->tl_data_contents = malloc(t2 + 1)) || - read_octet_string(filep, tl->tl_data_contents, t2)) { - try2read = read_nomem; - goto cleanup; - } - /* test to set mask fields */ - if (t1 == KRB5_TL_KADM_DATA) { + if (tl->tl_data_type == KRB5_TL_KADM_DATA) { XDR xdrs; osa_princ_ent_rec osa_princ_ent; @@ -2032,10 +2122,9 @@ process_k5beta6_record(char *fname, krb5_context kcontext, FILE *filep, if (flags & FLAG_VERBOSE) fprintf(stderr, add_princ_fmt, name); retval = 0; - error = 0; cleanup: - if (error) + if (retval > 0) fprintf(stderr, read_err_fmt, fname, *linenop, try2read); free(op); @@ -2110,7 +2199,7 @@ process_r1_8_policy(fname, kcontext, filep, flags, linenop) * 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", + nread = fscanf(filep, "%1024s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d%*[^\n]", rec.name, &rec.pw_min_life, &rec.pw_max_life, &rec.pw_min_length, &rec.pw_min_classes, @@ -2139,6 +2228,83 @@ process_r1_8_policy(fname, kcontext, filep, flags, linenop) return 0; } +static int +process_r1_11_policy(char *fname, krb5_context kcontext, FILE *filep, + int flags, int *linenop) +{ + osa_policy_ent_rec rec; + krb5_tl_data *tl, *tl_next; + char namebuf[1024]; + char keysaltbuf[KRB5_KDB_MAX_ALLOWED_KS_LEN + 1]; + int nread; + int ret = 0; + const char *try2read = NULL; + + memset(&rec, 0, sizeof(rec)); + + (*linenop)++; + rec.name = namebuf; + rec.allowed_keysalts = keysaltbuf; + + nread = fscanf(filep, + "%1023s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t" + "%d\t%d\t%d\t" + K5CONST_WIDTH_SCANF_STR(KRB5_KDB_MAX_ALLOWED_KS_LEN) + "\t%hd", + 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, + &rec.attributes, &rec.max_life, &rec.max_renewable_life, + rec.allowed_keysalts, &rec.n_tl_data); + if (nread == EOF) + return -1; + else if (nread != 15) { + fprintf(stderr, "cannot parse policy on line %d (%d read)\n", + *linenop, nread); + return 1; + } + + if (rec.allowed_keysalts && !strcmp(rec.allowed_keysalts, "-")) + rec.allowed_keysalts = NULL; + + /* Get TL data */ + ret = alloc_tl_data(rec.n_tl_data, &rec.tl_data); + if (ret) + goto cleanup; + + ret = process_tl_data(fname, filep, rec.tl_data, &try2read); + if (ret) + goto cleanup; + + if ((ret = krb5_db_create_policy(kcontext, &rec)) && + (ret = krb5_db_put_policy(kcontext, &rec))) { + fprintf(stderr, "cannot create policy on line %d: %s\n", + *linenop, error_message(ret)); + try2read = NULL; + goto cleanup; + } + if (flags & FLAG_VERBOSE) + fprintf(stderr, "created policy %s\n", rec.name); + +cleanup: + for (tl = rec.tl_data; tl; tl = tl_next) { + tl_next = tl->tl_data_next; + free(tl->tl_data_contents); + free(tl); + } + if (ret == ENOMEM) + try2read = no_mem_fmt; + if (ret) { + if (try2read) + fprintf(stderr, read_err_fmt, fname, *linenop, try2read); + return 1; + } + return 0; +} + /* * process_k5beta7_record() - Handle a dump record in krb5b7 format. * @@ -2250,6 +2416,36 @@ process_r1_8_record(fname, kcontext, filep, flags, linenop) } /* + * process_r1_11_record() - Handle a dump record in krb5 1.11 format. + * + * Returns -1 for end of file, 0 for success and 1 for failure. + */ +static int +process_r1_11_record(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")) + process_k5beta6_record(fname, kcontext, filep, flags, linenop); + else if (!strcmp(rectype, "policy")) + process_r1_11_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 @@ -2333,6 +2529,8 @@ load_db(argc, argv) load = &ov_version; else if (!strcmp(argv[aindex], r13option)) load = &r1_3_version; + else if (!strcmp(argv[aindex], r18option)) + load = &r1_8_version; else if (!strcmp(argv[aindex], ipropoption)) { if (log_ctx && log_ctx->iproprole) { load = &iprop_version; @@ -2426,6 +2624,8 @@ load_db(argc, argv) load = &r1_3_version; else if (strcmp(buf, r1_8_version.header) == 0) load = &r1_8_version; + else if (strcmp(buf, r1_11_version.header) == 0) + load = &r1_11_version; else if (strncmp(buf, ov_version.header, strlen(ov_version.header)) == 0) load = &ov_version; |