# # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 2018, Joyent, Inc. PROG= kdb5_util OBJS = kdb5_util.o \ kdb5_create.o kadm5_create.o string_table.o kdb5_stash.o \ kdb5_destroy.o ovload.o strtok.o dump.o SRCS = $(OBJS:.o=.c) CLOBBERFILES += $(TESTPROG) ISRCHDR= iprop.h KRB5IPROPDIR= $(SRC)/cmd/krb5/iprop include ../../../Makefile.cmd include $(SRC)/lib/gss_mechs/mech_krb5/Makefile.mech_krb5 POFILE = $(PROG).po POFILES = generic.po CPPFLAGS += -I. -I$(SRC)/lib/gss_mechs/mech_krb5/include/kerberosIV \ -I$(SRC)/lib/gss_mechs/mech_krb5/include \ -I$(SRC)/lib/gss_mechs/mech_krb5/include/krb5 \ -I$(SRC)/lib/krb5 \ -I$(SRC)/uts/common/gssapi/include \ -I$(SRC)/uts/common/gssapi/mechs/krb5/include \ -I$(KRB5IPROPDIR) \ -DHAVE_LIBSOCKET=1 -DHAVE_LIBNSL=1 -DHAVE_GETCWD=1 \ -DHAVE_STRSTR=1 -DHAVE_COMPILE=1 -DHAVE_STEP=1 \ -DHAVE_KRB_DB_H=1 -DHAVE_KDC_H=1 -DKDB4_DISABLE \ -DUSE_KADM5_API_VERSION=2 CERRWARN += -Wno-parentheses CERRWARN += -Wno-unused-variable CERRWARN += -Wno-unused-function CERRWARN += -Wno-implicit-function-declaration # Hammerhead: Suppress pointer/int cast warnings in legacy code CERRWARN += -Wno-pointer-to-int-cast CERRWARN += -Wno-int-to-pointer-cast # not linted SMATCH=off LDFLAGS += $(KRUNPATH) $(KERBRUNPATH) # Hammerhead: GNU ld needs rpath-link for transitive deps (libdyn, libkdb) via libkadm5srv LDFLAGS += -Wl,-rpath-link,$(ROOT)/usr/lib/krb5 LDLIBS += -L $(ROOT_KLIBDIR) -L $(KRB5LIB) -lkadm5srv -lkdb \ -lmech_krb5 -lnsl .KEEP_STATE: all: $(PROG) # Hammerhead: pre-generated (rpcgen + GNU cpp truncation bug) # iprop.h is now a committed source file. # Explicitly state the dependency on iprop.h $(OBJS): $(ISRCHDR) $(PROG): $(OBJS) $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) install: $(KRB5SBINPROG) clean: $(RM) $(OBJS) @# Hammerhead: do not delete pre-generated $(ISRCHDR) include ../../../Makefile.targ $(POFILE): $(DERIVED_FILES) .WAIT $(POFILES) $(RM) $@ $(CAT) $(POFILES) > $@ generic.po: FRC $(RM) messages.po $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext *.[ch]` $(SED) "/^domain/d" messages.po > $@ $(RM) messages.po FRC: /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * admin/edit/dump.c * * Copyright 1990,1991 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. * * * Dump a KDC database */ #include #include #include #include #include #include #include #include "kdb5_util.h" #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) #include #endif /* HAVE_REGEX_H */ /* * Needed for master key conversion. */ extern krb5_keyblock master_key; extern krb5_principal master_princ; static int mkey_convert; static krb5_keyblock new_master_key; static int backwards; static int recursive; /* * Use compile(3) if no regcomp present. */ #if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H) #define INIT char *sp = instring; #define GETC() (*sp++) #define PEEKC() (*sp) #define UNGETC(c) (--sp) #define RETURN(c) return(c) #define ERROR(c) #define RE_BUF_SIZE 1024 #include #endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */ struct dump_args { char *programname; FILE *ofile; krb5_context kcontext; char **names; int nnames; int verbose; }; static krb5_error_code dump_k5beta_iterator (krb5_pointer, krb5_db_entry *); static krb5_error_code dump_k5beta6_iterator (krb5_pointer, krb5_db_entry *); static krb5_error_code dump_k5beta6_iterator_ext (krb5_pointer, krb5_db_entry *, int); static krb5_error_code dump_iprop_iterator (krb5_pointer, krb5_db_entry *); static krb5_error_code dump_k5beta7_princ (krb5_pointer, krb5_db_entry *); static krb5_error_code dump_k5beta7_princ_ext (krb5_pointer, krb5_db_entry *, int); static krb5_error_code dump_k5beta7_princ_withpolicy (krb5_pointer, krb5_db_entry *); static krb5_error_code dump_iprop_princ (krb5_pointer, krb5_db_entry *); static krb5_error_code dump_ov_princ (krb5_pointer, krb5_db_entry *); static void dump_k5beta7_policy (void *, osa_policy_ent_t); typedef krb5_error_code (*dump_func)(krb5_pointer, krb5_db_entry *); static int process_k5beta_record (char *, krb5_context, FILE *, int, int *); 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_ov_record (char *, krb5_context, FILE *, int, int *); typedef krb5_error_code (*load_func)(char *, krb5_context, FILE *, int, int *); typedef struct _dump_version { char *name; char *header; int updateonly; int create_kadm5; dump_func dump_princ; osa_adb_iter_policy_func dump_policy; load_func load_record; } dump_version; dump_version old_version = { "Kerberos version 5 old format", "kdb5_edit load_dump version 2.0\n", 0, 1, dump_k5beta_iterator, NULL, process_k5beta_record }; dump_version beta6_version = { "Kerberos version 5 beta 6 format", "kdb5_edit load_dump version 3.0\n", 0, 1, dump_k5beta6_iterator, NULL, process_k5beta6_record }; dump_version beta7_version = { "Kerberos version 5", "kdb5_util load_dump version 4\n", 0, 0, dump_k5beta7_princ, dump_k5beta7_policy, process_k5beta7_record }; dump_version iprop_version = { "Kerberos iprop version", "iprop", 0, 0, dump_iprop_princ, dump_k5beta7_policy, process_k5beta7_record }; dump_version ov_version = { "OpenV*Secure V1.0", "OpenV*Secure V1.0\t", 1, 1, dump_ov_princ, dump_k5beta7_policy, process_ov_record }; dump_version r1_3_version = { "Kerberos version 5 release 1.3", "kdb5_util load_dump version 5\n", 0, 0, dump_k5beta7_princ_withpolicy, dump_k5beta7_policy, process_k5beta7_record, }; /* External data */ extern char *current_dbname; extern krb5_boolean dbactive; extern int exit_status; extern krb5_context util_context; extern kadm5_config_params global_params; /* Strings */ #define k5beta_dump_header "kdb5_edit load_dump version 2.0\n" static const char null_mprinc_name[] = "kdb5_dump@MISSING"; /* * We define gettext(s) to be s here, so that xgettext will extract the * strings to the .po file. At the end of the message section we will * undef gettext so that we can use it as a funtion. */ #define gettext(s) s /* Message strings */ static const char regex_err[] = gettext("%s: regular expression error - %s\n"); static const char regex_merr[] = gettext("%s: regular expression match error - %s\n"); static const char pname_unp_err[] = gettext("%s: cannot unparse principal name (%s)\n"); static const char mname_unp_err[] = gettext("%s: cannot unparse modifier name (%s)\n"); static const char nokeys_err[] = gettext("%s: cannot find any standard key for %s\n"); static const char sdump_tl_inc_err[] = gettext("%s: tagged data list inconsistency for %s " "(counted %d, stored %d)\n"); static const char stand_fmt_name[] = gettext("Kerberos version 5"); static const char old_fmt_name[] = gettext("Kerberos version 5 old format"); static const char b6_fmt_name[] = gettext("Kerberos version 5 beta 6 format"); static const char ofopen_error[] = gettext("%s: cannot open %s for writing (%s)\n"); static const char oflock_error[] = gettext("%s: cannot lock %s (%s)\n"); static const char dumprec_err[] = gettext("%s: error performing %s dump (%s)\n"); static const char dumphdr_err[] = gettext("%s: error dumping %s header (%s)\n"); static const char trash_end_fmt[] = gettext("%s(%d): ignoring trash at end of line: "); static const char read_name_string[] = gettext("name string"); static const char read_key_type[] = gettext("key type"); static const char read_key_data[] = gettext("key data"); static const char read_pr_data1[] = gettext("first set of principal attributes"); static const char read_mod_name[] = gettext("modifier name"); static const char read_pr_data2[] = gettext("second set of principal attributes"); static const char read_salt_data[] = gettext("salt data"); static const char read_akey_type[] = gettext("alternate key type"); static const char read_akey_data[] = gettext("alternate key data"); static const char read_asalt_type[] = gettext("alternate salt type"); static const char read_asalt_data[] = gettext("alternate salt data"); static const char read_exp_data[] = gettext("expansion data"); static const char store_err_fmt[] = gettext("%s(%d): cannot store %s(%s)\n"); static const char add_princ_fmt[] = gettext("%s\n"); static const char parse_err_fmt[] = gettext("%s(%d): cannot parse %s (%s)\n"); static const char read_err_fmt[] = gettext("%s(%d): cannot read %s\n"); static const char no_mem_fmt[] = gettext("%s(%d): no memory for buffers\n"); static const char rhead_err_fmt[] = gettext("%s(%d): cannot match size tokens\n"); static const char err_line_fmt[] = gettext("%s: error processing line %d of %s\n"); static const char head_bad_fmt[] = gettext("%s: dump header bad in %s\n"); static const char read_bytecnt[] = gettext("record byte count"); static const char read_encdata[] = gettext("encoded data"); static const char n_name_unp_fmt[] = gettext("%s(%s): cannot unparse name\n"); static const char n_dec_cont_fmt[] = gettext("%s(%s): cannot decode contents\n"); static const char read_nint_data[] = gettext("principal static attributes"); static const char read_tcontents[] = gettext("tagged data contents"); static const char read_ttypelen[] = gettext("tagged data type and length"); static const char read_kcontents[] = gettext("key data contents"); static const char read_ktypelen[] = gettext("key data type and length"); static const char read_econtents[] = gettext("extra data contents"); static const char k5beta_fmt_name[] = gettext("Kerberos version 5 old format"); static const char standard_fmt_name[] = gettext("Kerberos version 5 format"); static const char no_name_mem_fmt[] = gettext("%s: cannot get memory for temporary name\n"); static const char ctx_err_fmt[] = gettext("%s: cannot initialize Kerberos context\n"); static const char stdin_name[] = gettext("standard input"); static const char remaster_err_fmt[] = gettext("while re-encoding keys for principal %s with new master key"); static const char restfail_fmt[] = gettext("%s: %s restore failed\n"); static const char close_err_fmt[] = gettext("%s: cannot close database (%s)\n"); static const char dbinit_err_fmt[] = gettext("%s: cannot initialize database (%s)\n"); static const char dblock_err_fmt[] = gettext("%s: cannot initialize database lock (%s)\n"); static const char dbname_err_fmt[] = gettext("%s: cannot set database name to %s (%s)\n"); static const char dbdelerr_fmt[] = gettext("%s: cannot delete bad database %s (%s)\n"); static const char dbunlockerr_fmt[] = gettext("%s: cannot unlock database %s (%s)\n"); static const char dbrenerr_fmt[] = gettext("%s: cannot rename database %s to %s (%s)\n"); static const char dbcreaterr_fmt[] = gettext("%s: cannot create database %s (%s)\n"); static const char dfile_err_fmt[] = gettext("%s: cannot open %s (%s)\n"); /* * We now return you to your regularly scheduled program. */ #undef gettext static const char oldoption[] = "-old"; static const char b6option[] = "-b6"; static const char b7option[] = "-b7"; static const char ipropoption[] = "-i"; static const char verboseoption[] = "-verbose"; static const char updateoption[] = "-update"; static const char hashoption[] = "-hash"; static const char ovoption[] = "-ov"; static const char dump_tmptrail[] = "~"; /* * Re-encrypt the key_data with the new master key... */ static krb5_error_code master_key_convert(context, db_entry) krb5_context context; krb5_db_entry * db_entry; { krb5_error_code retval; krb5_keyblock v5plainkey, *key_ptr; krb5_keysalt keysalt; int i, j; krb5_key_data new_key_data, *key_data; krb5_boolean is_mkey; is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ); if (is_mkey && db_entry->n_key_data != 1) fprintf(stderr, gettext( "Master key db entry has %d keys, expecting only 1!\n"), db_entry->n_key_data); for (i=0; i < db_entry->n_key_data; i++) { key_data = &db_entry->key_data[i]; retval = krb5_dbekd_decrypt_key_data(context, &master_key, key_data, &v5plainkey, &keysalt); if (retval) return retval; memset(&new_key_data, 0, sizeof(new_key_data)); key_ptr = is_mkey ? &new_master_key : &v5plainkey; retval = krb5_dbekd_encrypt_key_data(context, &new_master_key, key_ptr, &keysalt, key_data->key_data_kvno, &new_key_data); if (retval) return retval; krb5_free_keyblock_contents(context, &v5plainkey); for (j = 0; j < key_data->key_data_ver; j++) { if (key_data->key_data_length[j]) { free(key_data->key_data_contents[j]); } } *key_data = new_key_data; } return 0; } /* * Update the "ok" file. */ void update_ok_file (file_name) char *file_name; { /* handle slave locking/failure stuff */ char *file_ok; int fd; static char ok[]=".dump_ok"; if ((file_ok = (char *)malloc(strlen(file_name) + strlen(ok) + 1)) == NULL) { com_err(progname, ENOMEM, gettext("while allocating filename " "for update_ok_file")); exit_status++; return; } strcpy(file_ok, file_name); strcat(file_ok, ok); if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) { com_err(progname, errno, gettext("while creating 'ok' file, '%s'"), file_ok); exit_status++; free(file_ok); return; } if (write(fd, "", 1) != 1) { com_err(progname, errno, gettext("while writing to 'ok' file, '%s'"), file_ok); exit_status++; free(file_ok); return; } free(file_ok); close(fd); return; } /* * name_matches() - See if a principal name matches a regular expression * or string. */ static int name_matches(name, arglist) char *name; struct dump_args *arglist; { #if HAVE_REGCOMP regex_t match_exp; regmatch_t match_match; int match_error; char match_errmsg[BUFSIZ]; size_t errmsg_size; #elif HAVE_REGEXP_H char regexp_buffer[RE_BUF_SIZE]; #elif HAVE_RE_COMP extern char *re_comp(); char *re_result; #endif /* HAVE_RE_COMP */ int i, match; /* * Plow, brute force, through the list of names/regular expressions. */ match = (arglist->nnames) ? 0 : 1; for (i=0; innames; i++) { #if HAVE_REGCOMP /* * Compile the regular expression. */ match_error = regcomp(&match_exp, arglist->names[i], REG_EXTENDED); if (match_error) { errmsg_size = regerror(match_error, &match_exp, match_errmsg, sizeof(match_errmsg)); fprintf(stderr, gettext(regex_err), arglist->programname, match_errmsg); break; } /* * See if we have a match. */ match_error = regexec(&match_exp, name, 1, &match_match, 0); if (match_error) { if (match_error != REG_NOMATCH) { errmsg_size = regerror(match_error, &match_exp, match_errmsg, sizeof(match_errmsg)); fprintf(stderr, gettext(regex_merr), arglist->programname, match_errmsg); break; } } else { /* * We have a match. See if it matches the whole * name. */ if ((match_match.rm_so == 0) && (match_match.rm_eo == strlen(name))) match = 1; } regfree(&match_exp); #elif HAVE_REGEXP_H /* * Compile the regular expression. */ compile(arglist->names[i], regexp_buffer, ®exp_buffer[RE_BUF_SIZE], '\0'); if (step(name, regexp_buffer)) { if ((loc1 == name) && (loc2 == &name[strlen(name)])) match = 1; } #elif HAVE_RE_COMP /* * Compile the regular expression. */ if (re_result = re_comp(arglist->names[i])) { fprintf(stderr, gettext(regex_err), arglist->programname, re_result); break; } if (re_exec(name)) match = 1; #else /* HAVE_RE_COMP */ /* * If no regular expression support, then just compare the strings. */ if (!strcmp(arglist->names[i], name)) match = 1; #endif /* HAVE_REGCOMP */ if (match) break; } return(match); } static krb5_error_code find_enctype(dbentp, enctype, salttype, kentp) krb5_db_entry *dbentp; krb5_enctype enctype; krb5_int32 salttype; krb5_key_data **kentp; { int i; int maxkvno; krb5_key_data *datap; maxkvno = -1; datap = (krb5_key_data *) NULL; for (i=0; in_key_data; i++) { if (( (krb5_enctype)dbentp->key_data[i].key_data_type[0] == enctype) && ((dbentp->key_data[i].key_data_type[1] == salttype) || (salttype < 0))) { maxkvno = dbentp->key_data[i].key_data_kvno; datap = &dbentp->key_data[i]; } } if (maxkvno >= 0) { *kentp = datap; return(0); } return(ENOENT); } #if 0 /* * dump_k5beta_header() - Make a dump header that is recognizable by Kerberos * Version 5 Beta 5 and previous releases. */ static krb5_error_code dump_k5beta_header(arglist) struct dump_args *arglist; { /* The old header consists of the leading string */ fprintf(arglist->ofile, k5beta_dump_header); return(0); } #endif /* * dump_k5beta_iterator() - Dump an entry in a format that is usable * by Kerberos Version 5 Beta 5 and previous * releases. */ static krb5_error_code dump_k5beta_iterator(ptr, entry) krb5_pointer ptr; krb5_db_entry *entry; { krb5_error_code retval; struct dump_args *arg; char *name, *mod_name; krb5_principal mod_princ; krb5_key_data *pkey, *akey, nullkey; krb5_timestamp mod_date, last_pwd_change; int i; /* Initialize */ arg = (struct dump_args *) ptr; name = (char *) NULL; mod_name = (char *) NULL; memset(&nullkey, 0, sizeof(nullkey)); /* * Flatten the principal name. */ if ((retval = krb5_unparse_name(arg->kcontext, entry->princ, &name))) { fprintf(stderr, gettext(pname_unp_err), arg->programname, error_message(retval)); return(retval); } /* * Re-encode the keys in the new master key, if necessary. */ if (mkey_convert) { retval = master_key_convert(arg->kcontext, entry); if (retval) { com_err(arg->programname, retval, remaster_err_fmt, name); return retval; } } /* * If we don't have any match strings, or if our name matches, then * proceed with the dump, otherwise, just forget about it. */ if (!arg->nnames || name_matches(name, arg)) { /* * Deserialize the modifier record. */ mod_name = (char *) NULL; mod_princ = NULL; last_pwd_change = mod_date = 0; pkey = akey = (krb5_key_data *) NULL; if (!(retval = krb5_dbe_lookup_mod_princ_data(arg->kcontext, entry, &mod_date, &mod_princ))) { if (mod_princ) { /* * Flatten the modifier name. */ if ((retval = krb5_unparse_name(arg->kcontext, mod_princ, &mod_name))) fprintf(stderr, gettext(mname_unp_err), arg->programname, error_message(retval)); krb5_free_principal(arg->kcontext, mod_princ); } } if (!mod_name) mod_name = strdup(null_mprinc_name); /* * Find the last password change record and set it straight. */ if ((retval = krb5_dbe_lookup_last_pwd_change(arg->kcontext, entry, &last_pwd_change))) { fprintf(stderr, gettext(nokeys_err), arg->programname, name); krb5_xfree(mod_name); krb5_xfree(name); return(retval); } /* * Find the 'primary' key and the 'alternate' key. */ if ((retval = find_enctype(entry, ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL, &pkey)) && (retval = find_enctype(entry, ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_V4, &akey))) { fprintf(stderr, gettext(nokeys_err), arg->programname, name); krb5_xfree(mod_name); krb5_xfree(name); return(retval); } /* If we only have one type, then ship it out as the primary. */ if (!pkey && akey) { pkey = akey; akey = &nullkey; } else { if (!akey) akey = &nullkey; } /* * First put out strings representing the length of the variable * length data in this record, then the name and the primary key type. */ fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%s\t%d\t", strlen(name), strlen(mod_name), (krb5_int32) pkey->key_data_length[0], (krb5_int32) akey->key_data_length[0], (krb5_int32) pkey->key_data_length[1], (krb5_int32) akey->key_data_length[1], name, (krb5_int32) pkey->key_data_type[0]); for (i=0; ikey_data_length[0]; i++) { fprintf(arg->ofile, "%02x", pkey->key_data_contents[0][i]); } /* * Second, print out strings representing the standard integer * data in this record. */ fprintf(arg->ofile, "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%s\t%u\t%u\t%u\t", (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, entry->attributes, pkey->key_data_type[1]); /* Pound out the salt data, if present. */ for (i=0; ikey_data_length[1]; i++) { fprintf(arg->ofile, "%02x", pkey->key_data_contents[1][i]); } /* Pound out the alternate key type and contents */ fprintf(arg->ofile, "\t%u\t", akey->key_data_type[0]); for (i=0; ikey_data_length[0]; i++) { fprintf(arg->ofile, "%02x", akey->key_data_contents[0][i]); } /* Pound out the alternate salt type and contents */ fprintf(arg->ofile, "\t%u\t", akey->key_data_type[1]); for (i=0; ikey_data_length[1]; i++) { fprintf(arg->ofile, "%02x", akey->key_data_contents[1][i]); } /* Pound out the expansion data. (is null) */ for (i=0; i < 8; i++) { fprintf(arg->ofile, "\t%u", 0); } fprintf(arg->ofile, ";\n"); /* If we're blabbing, do it */ if (arg->verbose) fprintf(stderr, "%s\n", name); krb5_xfree(mod_name); } krb5_xfree(name); return(0); } /* * dump_k5beta6_iterator() - Output a dump record in krb5b6 format. */ static krb5_error_code dump_k5beta6_iterator(ptr, entry) krb5_pointer ptr; krb5_db_entry *entry; { return dump_k5beta6_iterator_ext(ptr, entry, 0); } static krb5_error_code dump_k5beta6_iterator_ext(ptr, entry, kadm) krb5_pointer ptr; krb5_db_entry *entry; int kadm; { krb5_error_code retval; struct dump_args *arg; char *name; krb5_tl_data *tlp; krb5_key_data *kdata; int counter, skip, i, j; /* Initialize */ arg = (struct dump_args *) ptr; name = (char *) NULL; /* * Flatten the principal name. */ if ((retval = krb5_unparse_name(arg->kcontext, entry->princ, &name))) { fprintf(stderr, gettext(pname_unp_err), arg->programname, error_message(retval)); return(retval); } /* * Re-encode the keys in the new master key, if necessary. */ if (mkey_convert) { retval = master_key_convert(arg->kcontext, entry); if (retval) { com_err(arg->programname, retval, remaster_err_fmt, name); return retval; } } /* * If we don't have any match strings, or if our name matches, then * proceed with the dump, otherwise, just forget about it. */ if (!arg->nnames || name_matches(name, arg)) { /* * We'd like to just blast out the contents as they would appear in * the database so that we can just suck it back in, but it doesn't * lend itself to easy editing. */ /* * The dump format is as follows: * len strlen(name) n_tl_data n_key_data e_length * name * attributes max_life max_renewable_life expiration * pw_expiration last_success last_failed fail_auth_count * n_tl_data*[type length ] * n_key_data*[ver kvno ver*(type length )] * * Fields which are not encapsulated by angle-brackets are to appear * verbatim. A bracketed field's absence is indicated by a -1 in its * place */ /* * Make sure that the tagged list is reasonably correct. */ counter = skip = 0; for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) { /* * don't dump tl data types we know aren't understood by * earlier revisions [krb5-admin/89] */ switch (tlp->tl_data_type) { case KRB5_TL_KADM_DATA: if (kadm) counter++; else skip++; break; default: counter++; break; } } if (counter + skip == entry->n_tl_data) { /* Pound out header */ fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%s\t", (int) entry->len, strlen(name), counter, (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", entry->attributes, entry->max_life, entry->max_renewable_life, entry->expiration, entry->pw_expiration, entry->last_success, entry->last_failed, 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; itl_data_length; i++) fprintf(arg->ofile, "%02x", tlp->tl_data_contents[i]); else fprintf(arg->ofile, "%d", -1); fprintf(arg->ofile, "\t"); } /* Pound out key data */ for (counter=0; countern_key_data; counter++) { kdata = &entry->key_data[counter]; fprintf(arg->ofile, "%d\t%d\t", (int) kdata->key_data_ver, (int) kdata->key_data_kvno); for (i=0; ikey_data_ver; i++) { fprintf(arg->ofile, "%d\t%d\t", kdata->key_data_type[i], kdata->key_data_length[i]); if (kdata->key_data_length[i]) for (j=0; jkey_data_length[i]; j++) fprintf(arg->ofile, "%02x", kdata->key_data_contents[i][j]); else fprintf(arg->ofile, "%d", -1); fprintf(arg->ofile, "\t"); } } /* Pound out extra data */ if (entry->e_length) for (i=0; ie_length; i++) fprintf(arg->ofile, "%02x", entry->e_data[i]); else fprintf(arg->ofile, "%d", -1); /* Print trailer */ fprintf(arg->ofile, ";\n"); if (arg->verbose) fprintf(stderr, "%s\n", name); } else { fprintf(stderr, gettext(sdump_tl_inc_err), arg->programname, name, counter+skip, (int) entry->n_tl_data); retval = EINVAL; } } krb5_xfree(name); return(retval); } /* * dump_iprop_iterator() - Output a dump record in iprop format. */ static krb5_error_code dump_iprop_iterator(ptr, entry) krb5_pointer ptr; krb5_db_entry *entry; { krb5_error_code retval; struct dump_args *arg; char *name; krb5_tl_data *tlp; krb5_key_data *kdata; int counter, i, j; /* Initialize */ arg = (struct dump_args *) ptr; name = (char *) NULL; /* * Flatten the principal name. */ if ((retval = krb5_unparse_name(arg->kcontext, entry->princ, &name))) { fprintf(stderr, gettext(pname_unp_err), arg->programname, error_message(retval)); return(retval); } /* * Re-encode the keys in the new master key, if necessary. */ if (mkey_convert) { retval = master_key_convert(arg->kcontext, entry); if (retval) { com_err(arg->programname, retval, remaster_err_fmt, name); return retval; } } /* * If we don't have any match strings, or if our name matches, then * proceed with the dump, otherwise, just forget about it. */ if (!arg->nnames || name_matches(name, arg)) { /* * We'd like to just blast out the contents as they would * appear in the database so that we can just suck it back * in, but it doesn't lend itself to easy editing. */ /* * The dump format is as follows: len strlen(name) * n_tl_data n_key_data e_length name attributes max_life * max_renewable_life expiration pw_expiration last_success * last_failed fail_auth_count n_tl_data*[type length * ] n_key_data*[ver kvno ver*(type length * )] Fields which are not encapsulated * by angle-brackets are to appear verbatim. Bracketed * fields absence is indicated by a -1 in its place */ /* * Make sure that the tagged list is reasonably correct. */ counter = 0; for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) counter++; if (counter == entry->n_tl_data) { /* Pound out header */ fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%s\t", (int) entry->len, strlen(name), (int) entry->n_tl_data, (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", entry->attributes, entry->max_life, entry->max_renewable_life, entry->expiration, entry->pw_expiration, entry->last_success, entry->last_failed, entry->fail_auth_count); /* Pound out tagged data. */ for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) { 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 key data */ for (counter = 0; counter < entry->n_key_data; counter++) { kdata = &entry->key_data[counter]; fprintf(arg->ofile, "%d\t%d\t", (int) kdata->key_data_ver, (int) kdata->key_data_kvno); for (i=0; ikey_data_ver; i++) { fprintf(arg->ofile, "%d\t%d\t", kdata->key_data_type[i], kdata->key_data_length[i]); if (kdata->key_data_length[i]) for (j = 0; j < kdata-> key_data_length[i]; j++) fprintf(arg->ofile, "%02x", kdata-> key_data_contents [i][j]); else fprintf(arg->ofile, "%d", -1); fprintf(arg->ofile, "\t"); } } /* Pound out extra data */ if (entry->e_length) for (i=0; ie_length; i++) fprintf(arg->ofile, "%02x", entry->e_data[i]); else fprintf(arg->ofile, "%d", -1); /* Print trailer */ fprintf(arg->ofile, ";\n"); if (arg->verbose) fprintf(stderr, "%s\n", name); } else { fprintf(stderr, gettext(sdump_tl_inc_err), arg->programname, name, counter, (int) entry->n_tl_data); retval = EINVAL; } } krb5_xfree(name); return(retval); } /* * dump_k5beta7_iterator() - Output a dump record in krb5b7 format. */ static krb5_error_code dump_k5beta7_princ(ptr, entry) krb5_pointer ptr; krb5_db_entry *entry; { return dump_k5beta7_princ_ext(ptr, entry, 0); } static krb5_error_code dump_k5beta7_princ_ext(ptr, entry, kadm) krb5_pointer ptr; krb5_db_entry *entry; int kadm; { krb5_error_code retval; struct dump_args *arg; char *name; int tmp_nnames; /* Initialize */ arg = (struct dump_args *) ptr; name = (char *) NULL; /* * Flatten the principal name. */ if ((retval = krb5_unparse_name(arg->kcontext, entry->princ, &name))) { fprintf(stderr, gettext(pname_unp_err), arg->programname, error_message(retval)); return(retval); } /* * If we don't have any match strings, or if our name matches, then * proceed with the dump, otherwise, just forget about it. */ if (!arg->nnames || name_matches(name, arg)) { fprintf(arg->ofile, "princ\t"); /* save the callee from matching the name again */ tmp_nnames = arg->nnames; arg->nnames = 0; retval = dump_k5beta6_iterator_ext(ptr, entry, kadm); arg->nnames = tmp_nnames; } free(name); return retval; } /* * dump_iprop_princ() - Output a dump record in iprop format. * This was created in order to dump more data, such as kadm5 tl */ static krb5_error_code dump_iprop_princ(ptr, entry) krb5_pointer ptr; krb5_db_entry *entry; { krb5_error_code retval; struct dump_args *arg; char *name; int tmp_nnames; /* Initialize */ arg = (struct dump_args *) ptr; name = (char *) NULL; /* * Flatten the principal name. */ if ((retval = krb5_unparse_name(arg->kcontext, entry->princ, &name))) { fprintf(stderr, gettext(pname_unp_err), arg->programname, error_message(retval)); return(retval); } /* * If we don't have any match strings, or if our name matches, then * proceed with the dump, otherwise, just forget about it. */ if (!arg->nnames || name_matches(name, arg)) { fprintf(arg->ofile, "princ\t"); /* save the callee from matching the name again */ tmp_nnames = arg->nnames; arg->nnames = 0; retval = dump_iprop_iterator(ptr, entry); arg->nnames = tmp_nnames; } free(name); return (retval); } static krb5_error_code dump_k5beta7_princ_withpolicy(ptr, entry) krb5_pointer ptr; krb5_db_entry *entry; { return dump_k5beta7_princ_ext(ptr, entry, 1); } void dump_k5beta7_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\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); } static void print_key_data(FILE *f, krb5_key_data *key_data) { int c; fprintf(f, "%d\t%d\t", key_data->key_data_type[0], key_data->key_data_length[0]); for(c = 0; c < key_data->key_data_length[0]; c++) fprintf(f, "%02x ", key_data->key_data_contents[0][c]); } /* * Function: print_princ * * Purpose: output osa_adb_princ_ent data in a human * readable format (which is a format suitable for * ovsec_adm_import consumption) * * Arguments: * data (input) pointer to a structure containing a FILE * * and a record counter. * entry (input) entry to get dumped. * void * * Requires: * nuttin * * Effects: * writes data to the specified file pointerp. * * Modifies: * nuttin * */ static krb5_error_code dump_ov_princ(krb5_pointer ptr, krb5_db_entry *kdb) { char *princstr; int x, y, foundcrc; struct dump_args *arg; krb5_tl_data tl_data; osa_princ_ent_rec adb; XDR xdrs; arg = (struct dump_args *) ptr; /* * XXX Currently, lookup_tl_data always returns zero; it sets * tl_data->tl_data_length to zero if the type isn't found. * This should be fixed... */ /* * XXX Should this function do nothing for a principal with no * admin data, or print a record of "default" values? See * comment in server_kdb.c to help decide. */ tl_data.tl_data_type = KRB5_TL_KADM_DATA; if (krb5_dbe_lookup_tl_data(arg->kcontext, kdb, &tl_data) || (tl_data.tl_data_length == 0)) return 0; memset(&adb, 0, sizeof(adb)); xdrmem_create(&xdrs, (const 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); return(KADM5_XDR_FAILURE); } xdr_destroy(&xdrs); krb5_unparse_name(arg->kcontext, kdb->princ, &princstr); fprintf(arg->ofile, "princ\t%s\t", princstr); if(adb.policy == NULL) fputc('\t', arg->ofile); else fprintf(arg->ofile, "%s\t", adb.policy); fprintf(arg->ofile, "%lx\t%d\t%d\t%d", adb.aux_attributes, adb.old_key_len,adb.old_key_next, adb.admin_history_kvno); for (x = 0; x < adb.old_key_len; x++) { foundcrc = 0; for (y = 0; y < adb.old_keys[x].n_key_data; y++) { krb5_key_data *key_data = &adb.old_keys[x].key_data[y]; if (key_data->key_data_type[0] != ENCTYPE_DES_CBC_CRC) continue; if (foundcrc) { fprintf(stderr, gettext("Warning! Multiple DES-CBC-CRC " "keys for principal %s; skipping " "duplicates.\n"), princstr); continue; } foundcrc++; fputc('\t', arg->ofile); print_key_data(arg->ofile, key_data); } if (!foundcrc) fprintf(stderr, gettext("Warning! No DES-CBC-CRC key " "for principal %s, cannot generate " "OV-compatible record; skipping\n"), princstr); } fputc('\n', arg->ofile); free(princstr); return 0; } /* * usage is: * dump_db [-i] [-old] [-b6] [-b7] [-ov] [-verbose] [-mkey_convert] * [-new_mkey_file mkey_file] [-rev] [-recurse] * [filename [principals...]] */ void dump_db(argc, argv) int argc; char **argv; { FILE *f; struct dump_args arglist; /* Solaris Kerberos */ #if 0 char *programname; #endif char *ofile; krb5_error_code kret, retval; dump_version *dump; int aindex; krb5_boolean locked; char *new_mkey_file = 0; bool_t dump_sno = FALSE; kdb_log_context *log_ctx; /* Solaris Kerberos: adding support for -rev/recurse flags */ int db_arg_index = 0; char *db_args[3] = {NULL, NULL, NULL}; /* * Parse the arguments. */ /* Solaris Kerberos */ #if 0 programname = argv[0]; if (strrchr(programname, (int) '/')) programname = strrchr(argv[0], (int) '/') + 1; #endif ofile = (char *) NULL; dump = &r1_3_version; arglist.verbose = 0; new_mkey_file = 0; mkey_convert = 0; backwards = 0; recursive = 0; log_ctx = util_context->kdblog_context; /* * Parse the qualifiers. */ for (aindex = 1; aindex < argc; aindex++) { if (!strcmp(argv[aindex], oldoption)) dump = &old_version; else if (!strcmp(argv[aindex], b6option)) dump = &beta6_version; else if (!strcmp(argv[aindex], b7option)) dump = &beta7_version; else if (!strcmp(argv[aindex], ovoption)) dump = &ov_version; else if (!strcmp(argv[aindex], ipropoption)) { if (log_ctx && log_ctx->iproprole) { dump = &iprop_version; /* * dump_sno is used to indicate if the serial * # should be populated in the output * file to be used later by iprop for updating * the slave's update log when loading */ dump_sno = TRUE; } else { fprintf(stderr, gettext("Iprop not enabled\n")); exit_status++; return; } } else if (!strcmp(argv[aindex], verboseoption)) arglist.verbose++; else if (!strcmp(argv[aindex], "-mkey_convert")) mkey_convert = 1; else if (!strcmp(argv[aindex], "-new_mkey_file")) { new_mkey_file = argv[++aindex]; mkey_convert = 1; } else if (!strcmp(argv[aindex], "-rev")) { /* Solaris Kerberos: adding support for -rev/recurse flags */ /* hack to pass args to db specific plugin */ db_args[db_arg_index++] = "rev"; } else if (!strcmp(argv[aindex], "-recurse")) { /* hack to pass args to db specific plugin */ db_args[db_arg_index++] = "recurse"; } else break; } arglist.names = (char **) NULL; arglist.nnames = 0; if (aindex < argc) { ofile = argv[aindex]; aindex++; if (aindex < argc) { arglist.names = &argv[aindex]; arglist.nnames = argc - aindex; } } /* * Make sure the database is open. The policy database only has * to be opened if we try a dump that uses it. */ if (!dbactive) { /* Solaris Kerberos */ com_err(progname, 0, Err_no_database); /* Solaris Kerberos */ exit_status++; return; } /* * If we're doing a master key conversion, set up for it. */ if (mkey_convert) { if (!valid_master_key) { /* TRUE here means read the keyboard, but only once */ retval = krb5_db_fetch_mkey(util_context, master_princ, global_params.enctype, TRUE, FALSE, (char *) NULL, 0, &master_key); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while reading master key")); exit(1); } retval = krb5_db_verify_master_key(util_context, master_princ, &master_key); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while verifying master key")); exit(1); } } if (!new_mkey_file) printf(gettext("Please enter new master key....\n")); if ((retval = krb5_db_fetch_mkey(util_context, master_princ, global_params.enctype, (new_mkey_file == 0) ? (krb5_boolean) 1 : 0, TRUE, new_mkey_file, 0, &new_master_key))) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while reading new master key")); exit(1); } } kret = 0; locked = 0; if (ofile && strcmp(ofile, "-")) { /* * Discourage accidental dumping to filenames beginning with '-'. */ if (ofile[0] == '-') usage(); /* * Make sure that we don't open and truncate on the fopen, * since that may hose an on-going kprop process. * * We could also control this by opening for read and * write, doing an flock with LOCK_EX, and then * truncating the file once we have gotten the lock, * but that would involve more OS dependencies than I * want to get into. */ unlink(ofile); if (!(f = fopen(ofile, "w"))) { /* Solaris Kerberos */ fprintf(stderr, gettext(ofopen_error), progname, ofile, error_message(errno)); exit_status++; return; } if ((kret = krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_EXCLUSIVE))) { /* Solaris Kerberos */ fprintf(stderr, gettext(oflock_error), progname, ofile, error_message(kret)); exit_status++; } else locked = 1; } else { f = stdout; } if (f && !(kret)) { /* Solaris Kerberos */ arglist.programname = progname; arglist.ofile = f; arglist.kcontext = util_context; fprintf(arglist.ofile, "%s", dump->header); if (dump_sno) { if (ulog_map(util_context, &global_params, FKCOMMAND)) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: Could not map log\n"), progname); exit_status++; goto error; } /* * We grab the lock twice (once again in the iterator call), * but that's ok since the lock func handles incr locks held. */ if (krb5_db_lock(util_context, KRB5_LOCKMODE_SHARED)) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: Couldn't grab lock\n"), progname); exit_status++; goto error; } 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); } if (dump->header[strlen(dump->header)-1] != '\n') fputc('\n', arglist.ofile); /* Solaris Kerberos: adding support for -rev/recurse flags */ /* don't pass in db_args if there aren't any */ if ((kret = krb5_db_iterate(util_context, NULL, dump->dump_princ, (krb5_pointer) &arglist, db_arg_index > 0 ? (char **)&db_args : NULL))) { /* Solaris Kerberos */ fprintf(stderr, dumprec_err, progname, dump->name, error_message(kret)); exit_status++; if (dump_sno) (void) krb5_db_unlock(util_context); } if (dump->dump_policy && (kret = krb5_db_iter_policy( util_context, "*", dump->dump_policy, &arglist))) { /* Solaris Kerberos */ fprintf(stderr, gettext(dumprec_err), progname, dump->name, error_message(kret)); exit_status++; } error: if (ofile && f != stdout && !exit_status) { if (locked) { (void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK); locked = 0; } fclose(f); update_ok_file(ofile); } } if (locked) (void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK); } /* * Read a string of bytes while counting the number of lines passed. */ static int read_string(f, buf, len, lp) FILE *f; char *buf; int len; int *lp; { int c; int i, retval; retval = 0; for (i=0; itl_data; (pwchg) && (pwchg->tl_data_type != KRB5_TL_LAST_PWD_CHANGE); pwchg = pwchg->tl_data_next); /* Check to see if we found one. */ linked = 0; if (!pwchg) { /* No, allocate a new one */ if ((pwchg = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) { memset(pwchg, 0, sizeof(krb5_tl_data)); if (!(pwchg->tl_data_contents = (krb5_octet *) malloc(sizeof(krb5_timestamp)))) { free(pwchg); pwchg = (krb5_tl_data *) NULL; } else { pwchg->tl_data_type = KRB5_TL_LAST_PWD_CHANGE; pwchg->tl_data_length = (krb5_int16) sizeof(krb5_timestamp); } } } else linked = 1; /* Do we have an entry? */ if (pwchg && pwchg->tl_data_contents) { /* Encode it */ krb5_kdb_encode_int32(last_pwd_change, pwchg->tl_data_contents); /* Link it in if necessary */ if (!linked) { pwchg->tl_data_next = dbentp->tl_data; dbentp->tl_data = pwchg; dbentp->n_tl_data++; } } else kret = ENOMEM; } return(kret); } #endif /* * process_k5beta_record() - Handle a dump record in old format. * * Returns -1 for end of file, 0 for success and 1 for failure. */ static int process_k5beta_record(fname, kcontext, filep, verbose, linenop) char *fname; krb5_context kcontext; FILE *filep; int verbose; int *linenop; { int nmatched; int retval; krb5_db_entry dbent; int name_len, mod_name_len, key_len; int alt_key_len, salt_len, alt_salt_len; char *name; char *mod_name; int tmpint1, tmpint2, tmpint3; int error; const char *try2read; int i; krb5_key_data *pkey, *akey; krb5_timestamp last_pwd_change, mod_date; krb5_principal mod_princ; krb5_error_code kret; krb5_octet *shortcopy1 = NULL; /* SUNWresync121 memleak fix */ krb5_octet *shortcopy2 = NULL; try2read = (char *) NULL; (*linenop)++; retval = 1; memset((char *)&dbent, 0, sizeof(dbent)); /* Make sure we've got key_data entries */ if (krb5_dbe_create_key_data(kcontext, &dbent) || krb5_dbe_create_key_data(kcontext, &dbent)) { krb5_db_free_principal(kcontext, &dbent, 1); return(1); } pkey = &dbent.key_data[0]; akey = &dbent.key_data[1]; /* * Match the sizes. 6 tokens to match. */ nmatched = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t", &name_len, &mod_name_len, &key_len, &alt_key_len, &salt_len, &alt_salt_len); if (nmatched == 6) { pkey->key_data_length[0] = key_len; akey->key_data_length[0] = alt_key_len; pkey->key_data_length[1] = salt_len; akey->key_data_length[1] = alt_salt_len; name = (char *) NULL; mod_name = (char *) NULL; /* * Get the memory for the variable length fields. */ if ((name = (char *) malloc((size_t) (name_len + 1))) && (mod_name = (char *) malloc((size_t) (mod_name_len + 1))) && (!key_len || (pkey->key_data_contents[0] = (krb5_octet *) malloc((size_t) (key_len + 1)))) && (!alt_key_len || (akey->key_data_contents[0] = (krb5_octet *) malloc((size_t) (alt_key_len + 1)))) && (!salt_len || (pkey->key_data_contents[1] = (krb5_octet *) malloc((size_t) (salt_len + 1)))) && (!alt_salt_len || (akey->key_data_contents[1] = (krb5_octet *) malloc((size_t) (alt_salt_len + 1)))) ) { error = 0; /* Read the principal name */ if (read_string(filep, name, name_len, linenop)) { try2read = read_name_string; error++; } /* Read the key type */ if (!error && (fscanf(filep, "\t%d\t", &tmpint1) != 1)) { try2read = read_key_type; error++; } pkey->key_data_type[0] = tmpint1; /* Read the old format key */ if (!error && read_octet_string(filep, pkey->key_data_contents[0], pkey->key_data_length[0])) { try2read = read_key_data; error++; } /* convert to a new format key */ /* the encrypted version is stored as the unencrypted key length (4 bytes, MSB first) followed by the encrypted key. */ if ((pkey->key_data_length[0] > 4) && (pkey->key_data_contents[0][0] == 0) && (pkey->key_data_contents[0][1] == 0)) { /* this really does look like an old key, so drop and swap */ /* the *new* length is 2 bytes, LSB first, sigh. */ size_t shortlen = pkey->key_data_length[0]-4+2; krb5_octet *origdata = pkey->key_data_contents[0]; shortcopy1 = (krb5_octet *) malloc(shortlen); if (shortcopy1) { shortcopy1[0] = origdata[3]; shortcopy1[1] = origdata[2]; memcpy(shortcopy1 + 2, origdata + 4, shortlen - 2); free(origdata); pkey->key_data_length[0] = shortlen; pkey->key_data_contents[0] = shortcopy1; } else { fprintf(stderr, gettext(no_mem_fmt), fname, *linenop); error++; } } /* Read principal attributes */ if (!error && (fscanf(filep, "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t", &tmpint1, &dbent.max_life, &dbent.max_renewable_life, &tmpint2, &dbent.expiration, &dbent.pw_expiration, &last_pwd_change, &dbent.last_success, &dbent.last_failed, &tmpint3) != 10)) { try2read = read_pr_data1; error++; } pkey->key_data_kvno = tmpint1; dbent.fail_auth_count = tmpint3; /* Read modifier name */ if (!error && read_string(filep, mod_name, mod_name_len, linenop)) { try2read = read_mod_name; error++; } /* Read second set of attributes */ if (!error && (fscanf(filep, "\t%u\t%u\t%u\t", &mod_date, &dbent.attributes, &tmpint1) != 3)) { try2read = read_pr_data2; error++; } pkey->key_data_type[1] = tmpint1; /* Read salt data */ if (!error && read_octet_string(filep, pkey->key_data_contents[1], pkey->key_data_length[1])) { try2read = read_salt_data; error++; } /* Read alternate key type */ if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) { try2read = read_akey_type; error++; } akey->key_data_type[0] = tmpint1; /* Read alternate key */ if (!error && read_octet_string(filep, akey->key_data_contents[0], akey->key_data_length[0])) { try2read = read_akey_data; error++; } /* convert to a new format key */ /* the encrypted version is stored as the unencrypted key length (4 bytes, MSB first) followed by the encrypted key. */ if ((akey->key_data_length[0] > 4) && (akey->key_data_contents[0][0] == 0) && (akey->key_data_contents[0][1] == 0)) { /* this really does look like an old key, so drop and swap */ /* the *new* length is 2 bytes, LSB first, sigh. */ size_t shortlen = akey->key_data_length[0]-4+2; krb5_octet *origdata = akey->key_data_contents[0]; shortcopy2 = (krb5_octet *) malloc(shortlen); if (shortcopy2) { shortcopy2[0] = origdata[3]; shortcopy2[1] = origdata[2]; memcpy(shortcopy2 + 2, origdata + 4, shortlen - 2); free(origdata); akey->key_data_length[0] = shortlen; akey->key_data_contents[0] = shortcopy2; } else { fprintf(stderr, gettext(no_mem_fmt), fname, *linenop); error++; } } /* Read alternate salt type */ if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) { try2read = read_asalt_type; error++; } akey->key_data_type[1] = tmpint1; /* Read alternate salt data */ if (!error && read_octet_string(filep, akey->key_data_contents[1], akey->key_data_length[1])) { try2read = read_asalt_data; error++; } /* Read expansion data - discard it */ if (!error) { for (i=0; i<8; i++) { if (fscanf(filep, "\t%u", &tmpint1) != 1) { try2read = read_exp_data; error++; break; } } if (!error) find_record_end(filep, fname, *linenop); } /* * If no error, then we're done reading. Now parse the names * and store the database dbent. */ if (!error) { if (!(kret = krb5_parse_name(kcontext, name, &dbent.princ))) { if (!(kret = krb5_parse_name(kcontext, mod_name, &mod_princ))) { if (!(kret = krb5_dbe_update_mod_princ_data(kcontext, &dbent, mod_date, mod_princ)) && !(kret = krb5_dbe_update_last_pwd_change(kcontext, &dbent, last_pwd_change))) { int one = 1; dbent.len = KRB5_KDB_V1_BASE_LENGTH; pkey->key_data_ver = (pkey->key_data_type[1] || pkey->key_data_length[1]) ? 2 : 1; akey->key_data_ver = (akey->key_data_type[1] || akey->key_data_length[1]) ? 2 : 1; if ((pkey->key_data_type[0] == akey->key_data_type[0]) && (pkey->key_data_type[1] == akey->key_data_type[1])) dbent.n_key_data--; else if ((akey->key_data_type[0] == 0) && (akey->key_data_length[0] == 0) && (akey->key_data_type[1] == 0) && (akey->key_data_length[1] == 0)) dbent.n_key_data--; dbent.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_KEY_DATA | KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS | KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT; if ((kret = krb5_db_put_principal(kcontext, &dbent, &one)) || (one != 1)) { fprintf(stderr, gettext(store_err_fmt), fname, *linenop, name, error_message(kret)); error++; } else { if (verbose) fprintf(stderr, gettext(add_princ_fmt), name); retval = 0; } dbent.n_key_data = 2; } krb5_free_principal(kcontext, mod_princ); } else { fprintf(stderr, gettext(parse_err_fmt), fname, *linenop, mod_name, error_message(kret)); error++; } } else { fprintf(stderr, gettext(parse_err_fmt), fname, *linenop, name, error_message(kret)); error++; } } else { fprintf(stderr, gettext(no_mem_fmt), fname, *linenop, try2read); } } else { fprintf(stderr, gettext(read_err_fmt), fname, *linenop); } krb5_db_free_principal(kcontext, &dbent, 1); if (mod_name) free(mod_name); if (name) free(name); } else { if (nmatched != EOF) fprintf(stderr, gettext(rhead_err_fmt), fname, *linenop); else retval = -1; } if (shortcopy1) free(shortcopy1); if (shortcopy2) free(shortcopy2); return(retval); } /* * process_k5beta6_record() - Handle a dump record in krb5b6 format. * * Returns -1 for end of file, 0 for success and 1 for failure. */ static int process_k5beta6_record(fname, kcontext, filep, verbose, linenop) char *fname; krb5_context kcontext; FILE *filep; int verbose; int *linenop; { int retval; krb5_db_entry dbentry; krb5_int32 t1, t2, t3, t4, t5, t6, t7, t8, t9; int nread; int error; int i, j, one; char *name; krb5_key_data *kp, *kdatap; krb5_tl_data **tlp, *tl; krb5_octet *op; krb5_error_code kret; const char *try2read; try2read = (char *) NULL; memset((char *) &dbentry, 0, sizeof(dbentry)); (*linenop)++; retval = 1; name = (char *) NULL; kp = (krb5_key_data *) NULL; op = (krb5_octet *) NULL; error = 0; kret = 0; nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t", &t1, &t2, &t3, &t4, &t5); if (nread == 5) { /* Get memory for flattened principal name */ if (!(name = (char *) malloc((size_t) t2 + 1))) error++; /* Get memory for and form tagged data linked list */ tlp = &dbentry.tl_data; for (i=0; itl_data_next); dbentry.n_tl_data++; } else { error++; break; } } /* Get memory for key list */ if (t4 && !(kp = (krb5_key_data *) malloc((size_t) (t4*sizeof(krb5_key_data))))) error++; /* Get memory for extra data */ if (t5 && !(op = (krb5_octet *) malloc((size_t) t5))) error++; if (!error) { dbentry.len = t1; dbentry.n_key_data = t4; dbentry.e_length = t5; if (kp) { memset(kp, 0, (size_t) (t4*sizeof(krb5_key_data))); dbentry.key_data = kp; kp = (krb5_key_data *) NULL; } if (op) { memset(op, 0, (size_t) t5); dbentry.e_data = op; op = (krb5_octet *) NULL; } /* Read in and parse the principal name */ if (!read_string(filep, name, t2, linenop) && !(kret = krb5_parse_name(kcontext, name, &dbentry.princ))) { /* Get the fixed principal attributes */ nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9); if (nread == 8) { dbentry.attributes = (krb5_flags) t2; dbentry.max_life = (krb5_deltat) t3; dbentry.max_renewable_life = (krb5_deltat) t4; dbentry.expiration = (krb5_timestamp) t5; dbentry.pw_expiration = (krb5_timestamp) t6; dbentry.last_success = (krb5_timestamp) t7; dbentry.last_failed = (krb5_timestamp) t8; dbentry.fail_auth_count = (krb5_kvno) t9; dbentry.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS | KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT; } else { try2read = read_nint_data; error++; } /* * Get the tagged data. * * Really, this code ought to discard tl data types * that it knows are special to the current version * and were not supported in the previous version. * But it's a pain to implement that here, and doing * it at dump time has almost as good an effect, so * that's what I did. [krb5-admin/89] */ if (!error && dbentry.n_tl_data) { for (tl = dbentry.tl_data; tl; tl = tl->tl_data_next) { nread = fscanf(filep, "%d\t%d\t", &t1, &t2); if (nread == 2) { tl->tl_data_type = (krb5_int16) t1; tl->tl_data_length = (krb5_int16) t2; if (tl->tl_data_length) { if (!(tl->tl_data_contents = (krb5_octet *) malloc((size_t) t2+1)) || read_octet_string(filep, tl->tl_data_contents, t2)) { try2read = read_tcontents; error++; break; } /* test to set mask fields */ if (t1 == KRB5_TL_KADM_DATA) { XDR xdrs; osa_princ_ent_rec osa_princ_ent; /* * Assuming aux_attributes will always be * there */ dbentry.mask |= KADM5_AUX_ATTRIBUTES; /* test for an actual policy reference */ memset(&osa_princ_ent, 0, sizeof(osa_princ_ent)); xdrmem_create(&xdrs, (char *)tl->tl_data_contents, tl->tl_data_length, XDR_DECODE); if (xdr_osa_princ_ent_rec(&xdrs, &osa_princ_ent) && (osa_princ_ent.aux_attributes & KADM5_POLICY) && osa_princ_ent.policy != NULL) { dbentry.mask |= KADM5_POLICY; kdb_free_entry(NULL, NULL, &osa_princ_ent); } xdr_destroy(&xdrs); } } else { /* Should be a null field */ nread = fscanf(filep, "%d", &t9); if ((nread != 1) || (t9 != -1)) { error++; try2read = read_tcontents; break; } } } else { try2read = read_ttypelen; error++; break; } } if (!error) dbentry.mask |= KADM5_TL_DATA; } /* Get the key data */ if (!error && dbentry.n_key_data) { for (i=0; !error && (ikey_data_ver = (krb5_int16) t1; kdatap->key_data_kvno = (krb5_int16) t2; for (j=0; jkey_data_type[j] = t3; kdatap->key_data_length[j] = t4; if (t4) { if (!(kdatap->key_data_contents[j] = (krb5_octet *) malloc((size_t) t4+1)) || read_octet_string(filep, kdatap->key_data_contents[j], t4)) { try2read = read_kcontents; error++; break; } } else { /* Should be a null field */ nread = fscanf(filep, "%d", &t9); if ((nread != 1) || (t9 != -1)) { error++; try2read = read_kcontents; break; } } } else { try2read = read_ktypelen; error++; break; } } } } if (!error) dbentry.mask |= KADM5_KEY_DATA; } /* Get the extra data */ if (!error && dbentry.e_length) { if (read_octet_string(filep, dbentry.e_data, (int) dbentry.e_length)) { try2read = read_econtents; error++; } } else { nread = fscanf(filep, "%d", &t9); if ((nread != 1) || (t9 != -1)) { error++; try2read = read_econtents; } } /* Finally, find the end of the record. */ if (!error) find_record_end(filep, fname, *linenop); /* * We have either read in all the data or choked. */ if (!error) { one = 1; if ((kret = krb5_db_put_principal(kcontext, &dbentry, &one))) { fprintf(stderr, gettext(store_err_fmt), fname, *linenop, name, error_message(kret)); } else { if (verbose) fprintf(stderr, gettext( add_princ_fmt), name); retval = 0; } } else { fprintf(stderr, gettext(read_err_fmt), fname, *linenop, try2read); } } else { if (kret) fprintf(stderr, gettext(parse_err_fmt), fname, *linenop, name, error_message(kret)); else fprintf(stderr, gettext(no_mem_fmt), fname, *linenop); } } else { fprintf(stderr, gettext(rhead_err_fmt), fname, *linenop); } if (op) free(op); if (kp) free(kp); if (name) free(name); krb5_db_free_principal(kcontext, &dbentry, 1); } else { if (nread == EOF) retval = -1; } return(retval); } static int process_k5beta7_policy(fname, kcontext, filep, verbose, linenop, pol_db) char *fname; krb5_context kcontext; FILE *filep; int verbose; int *linenop; void *pol_db; { osa_policy_ent_rec rec; char namebuf[1024]; int nread, ret; (*linenop)++; rec.name = namebuf; nread = fscanf(filep, "%1024s\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); if (nread == EOF) return -1; else if (nread != 7) { fprintf(stderr, gettext("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, gettext("cannot create policy on line %d: %s\n"), *linenop, error_message(ret)); return 1; } } if (verbose) fprintf(stderr, gettext("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) char *fname; krb5_context kcontext; FILE *filep; int verbose; 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, verbose, linenop); else if (strcmp(rectype, "policy") == 0) process_k5beta7_policy(fname, kcontext, filep, verbose, linenop); else { fprintf(stderr, gettext("unknown record type \"%s\" on line %d\n"), rectype, *linenop); return 1; } return 0; } /* * process_ov_record() - Handle a dump record in OpenV*Secure 1.0 format. * * Returns -1 for end of file, 0 for success and 1 for failure. */ static int process_ov_record(fname, kcontext, filep, verbose, linenop) char *fname; krb5_context kcontext; FILE *filep; int verbose; 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_ov_principal(fname, kcontext, filep, verbose, linenop); else if (strcmp(rectype, "policy") == 0) process_k5beta7_policy(fname, kcontext, filep, verbose, linenop); else if (strcmp(rectype, "End") == 0) return -1; else { fprintf(stderr, gettext("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) char *programname; krb5_context kcontext; char *dumpfile; FILE *f; int verbose; dump_version *dump; { int error; int lineno; error = 0; lineno = 1; /* * Process the records. */ while (!(error = (*dump->load_record)(dumpfile, kcontext, f, verbose, &lineno))) ; if (error != -1) fprintf(stderr, gettext(err_line_fmt), programname, lineno, dumpfile); else error = 0; return(error); } /* * Usage: load_db [-i] [-old] [-ov] [-b6] [-b7] [-verbose] [-update] [-hash] * filename */ void load_db(argc, argv) int argc; char **argv; { kadm5_config_params newparams; krb5_error_code kret; krb5_context kcontext; FILE *f; extern char *optarg; extern int optind; /* Solaris Kerberos */ #if 0 char *programname; #endif char *dumpfile; char *dbname; char *dbname_tmp; char buf[BUFSIZ]; dump_version *load; int update, verbose; int aindex; bool_t add_update = TRUE; char iheader[MAX_HEADER]; uint32_t caller, last_sno, last_seconds, last_useconds; kdb_log_context *log_ctx; int db_locked = 0; /* * Parse the arguments. */ /* Solaris Kerberos */ #if 0 programname = argv[0]; if (strrchr(programname, (int) '/')) programname = strrchr(argv[0], (int) '/') + 1; #endif dumpfile = (char *) NULL; dbname = global_params.dbname; load = NULL; update = 0; verbose = 0; exit_status = 0; dbname_tmp = (char *) NULL; log_ctx = util_context->kdblog_context; for (aindex = 1; aindex < argc; aindex++) { if (!strcmp(argv[aindex], oldoption)) load = &old_version; else if (!strcmp(argv[aindex], b6option)) load = &beta6_version; else if (!strcmp(argv[aindex], b7option)) load = &beta7_version; else if (!strcmp(argv[aindex], ovoption)) load = &ov_version; else if (!strcmp(argv[aindex], ipropoption)) { if (log_ctx && log_ctx->iproprole) { load = &iprop_version; add_update = FALSE; } else { fprintf(stderr, gettext("Iprop not enabled\n")); exit_status++; return; } } else if (!strcmp(argv[aindex], verboseoption)) verbose = 1; else if (!strcmp(argv[aindex], updateoption)) update = 1; else if (!strcmp(argv[aindex], hashoption)) { if (!add_db_arg("hash=true")) { com_err(progname, ENOMEM, "while parsing command arguments\n"); exit(1); } } else break; } if ((argc - aindex) != 1) { usage(); return; } dumpfile = argv[aindex]; if (!(dbname_tmp = (char *) malloc(strlen(dbname)+ strlen(dump_tmptrail)+1))) { /* Solaris Kerberos */ fprintf(stderr, gettext(no_name_mem_fmt), progname); exit_status++; return; } strcpy(dbname_tmp, dbname); strcat(dbname_tmp, dump_tmptrail); /* * Initialize the Kerberos context and error tables. */ if ((kret = kadm5_init_krb5_context(&kcontext))) { /* Solaris Kerberos */ fprintf(stderr, gettext(ctx_err_fmt), progname); free(dbname_tmp); exit_status++; return; } if( (kret = krb5_set_default_realm(kcontext, util_context->default_realm)) ) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: Unable to set the default realm\n"), progname); free(dbname_tmp); exit_status++; return; } if (log_ctx && log_ctx->iproprole) kcontext->kdblog_context = (void *)log_ctx; /* * Open the dumpfile */ if (dumpfile) { if ((f = fopen(dumpfile, "r")) == NULL) { /* Solaris Kerberos */ fprintf(stderr, gettext(dfile_err_fmt), progname, dumpfile, error_message(errno)); exit_status++; return; } if ((kret = krb5_lock_file(kcontext, fileno(f), KRB5_LOCKMODE_SHARED))) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: Cannot lock %s: %s\n"), progname, dumpfile, error_message(errno)); exit_status++; return; } } else f = stdin; /* * Auto-detect dump version if we weren't told, verify if we * were told. */ fgets(buf, sizeof(buf), f); if (load) { /* only check what we know; some headers only contain a prefix */ if (strncmp(buf, load->header, strlen(load->header)) != 0) { /* Solaris Kerberos */ fprintf(stderr, gettext(head_bad_fmt), progname, dumpfile); exit_status++; if (dumpfile) fclose(f); return; } } else { /* perhaps this should be in an array, but so what? */ if (strcmp(buf, old_version.header) == 0) load = &old_version; else if (strcmp(buf, beta6_version.header) == 0) load = &beta6_version; else if (strcmp(buf, beta7_version.header) == 0) load = &beta7_version; else if (strcmp(buf, r1_3_version.header) == 0) load = &r1_3_version; else if (strncmp(buf, ov_version.header, strlen(ov_version.header)) == 0) load = &ov_version; else { /* Solaris Kerberos */ fprintf(stderr, gettext(head_bad_fmt), progname, dumpfile); exit_status++; if (dumpfile) fclose(f); return; } } if (load->updateonly && !update) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: dump version %s can only " "be loaded with the -update flag\n"), progname, load->name); exit_status++; return; } /* * Cons up params for the new databases. If we are not in update * mode, we create an alternate database and then promote it to * be the live db. */ newparams = global_params; if (! update) { newparams.mask |= KADM5_CONFIG_DBNAME; newparams.dbname = dbname_tmp; if ((kret = kadm5_get_config_params(kcontext, 1, &newparams, &newparams))) { /* Solaris Kerberos */ com_err(progname, kret, gettext("while retreiving new " "configuration parameters")); exit_status++; return; } if (!add_db_arg("temporary")) { com_err(progname, ENOMEM, "computing parameters for database"); exit(1); } } /* * If not an update restoration, create the database. otherwise open */ if (!update) { if((kret = krb5_db_create(kcontext, db5util_db_args))) { const char *emsg = krb5_get_error_message(kcontext, kret); /* * See if something (like DAL KDB plugin) has set a specific error * message and use that otherwise use default. */ if (emsg != NULL) { /* Solaris Kerberos */ fprintf(stderr, "%s: %s\n", progname, emsg); krb5_free_error_message (kcontext, emsg); } else { /* Solaris Kerberos */ fprintf(stderr, dbcreaterr_fmt, progname, dbname, error_message(kret)); } exit_status++; kadm5_free_config_params(kcontext, &newparams); if (dumpfile) fclose(f); return; } } else { /* * Initialize the database. */ if ((kret = krb5_db_open(kcontext, db5util_db_args, KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) { const char *emsg = krb5_get_error_message(kcontext, kret); /* * See if something (like DAL KDB plugin) has set a specific * error message and use that otherwise use default. */ if (emsg != NULL) { /* Solaris Kerberos */ fprintf(stderr, "%s: %s\n", progname, emsg); krb5_free_error_message (kcontext, emsg); } else { /* Solaris Kerberos */ fprintf(stderr, dbinit_err_fmt, progname, error_message(kret)); } exit_status++; goto error; } } /* * 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))) { /* * Ignore a not supported error since there is nothing to do about it * anyway. */ if (kret != KRB5_PLUGIN_OP_NOTSUPP) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: %s while permanently locking database\n"), progname, error_message(kret)); exit_status++; goto error; } } else { db_locked = 1; } if (log_ctx && log_ctx->iproprole) { if (add_update) caller = FKCOMMAND; else caller = FKPROPD; if (ulog_map(kcontext, &global_params, caller)) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: Could not map log\n"), progname); exit_status++; goto error; } /* * We don't want to take out the ulog out from underneath * kadmind so we reinit the header log. * * We also don't want to add to the update log since we * are doing a whole sale replace of the db, because: * we could easily exceed # of update entries * we could implicity delete db entries during a replace * no advantage in incr updates when entire db is replaced */ if (!update) { memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t)); log_ctx->ulog->kdb_hmagic = KDB_HMAGIC; log_ctx->ulog->db_version_num = KDB_VERSION; log_ctx->ulog->kdb_state = KDB_STABLE; log_ctx->ulog->kdb_block = ULOG_BLOCK; log_ctx->iproprole = IPROP_NULL; if (!add_update) { sscanf(buf, "%s %u %u %u", iheader, &last_sno, &last_seconds, &last_useconds); log_ctx->ulog->kdb_last_sno = last_sno; log_ctx->ulog->kdb_last_time.seconds = last_seconds; log_ctx->ulog->kdb_last_time.useconds = last_useconds; } } } /* Solaris Kerberos */ if (restore_dump(progname, kcontext, (dumpfile) ? dumpfile : stdin_name, f, verbose, load)) { /* Solaris Kerberos */ fprintf(stderr, gettext(restfail_fmt), progname, load->name); exit_status++; } if (!update && load->create_kadm5 && ((kret = kadm5_create_magic_princs(&newparams, kcontext)))) { /* error message printed by create_magic_princs */ exit_status++; } if (db_locked && (kret = krb5_db_unlock(kcontext))) { /* change this error? */ /* Solaris Kerberos */ fprintf(stderr, gettext(dbunlockerr_fmt), progname, dbname, error_message(kret)); exit_status++; } #if 0 if ((kret = krb5_db_fini(kcontext))) { /* Solaris Kerberos */ fprintf(stderr, gettext(close_err_fmt), progname, error_message(kret)); exit_status++; } #endif /* close policy db below */ if (exit_status == 0 && !update) { kret = krb5_db_promote(kcontext, db5util_db_args); /* * Ignore a not supported error since there is nothing to do about it * anyway. */ if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) { /* Solaris Kerberos */ fprintf(stderr, gettext("%s: cannot make newly loaded database live (%s)\n"), progname, error_message(kret)); exit_status++; } } error: /* * If not an update: if there was an error, destroy the temp database, * otherwise rename it into place. * * If an update: if there was no error, unlock the database. */ if (!update) { if (exit_status) { kret = krb5_db_destroy(kcontext, db5util_db_args); /* * Ignore a not supported error since there is nothing to do about * it anyway. */ if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) { /* Solaris Kerberos */ fprintf(stderr, gettext(dbdelerr_fmt), progname, dbname, error_message(kret)); exit_status++; } } } if (dumpfile) { (void) krb5_lock_file(kcontext, fileno(f), KRB5_LOCKMODE_UNLOCK); fclose(f); } if (dbname_tmp) free(dbname_tmp); krb5_free_context(kcontext); } /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * import_err.h: * This file is automatically generated; please do not edit it. */ #include #define IMPORT_NO_ERR (37349888L) #define IMPORT_BAD_FILE (37349889L) #define IMPORT_BAD_TOKEN (37349890L) #define IMPORT_BAD_VERSION (37349891L) #define IMPORT_BAD_RECORD (37349892L) #define IMPORT_BAD_FOOTER (37349893L) #define IMPORT_FAILED (37349894L) #define IMPORT_COUNT_MESSAGE (37349895L) #define IMPORT_MISMATCH_COUNT (37349896L) #define IMPORT_UNK_OPTION (37349897L) #define IMPORT_WARN_DB (37349898L) #define IMPORT_RENAME_FAILED (37349899L) #define IMPORT_EXTRA_DATA (37349900L) #define IMPORT_CONFIRM (37349901L) #define IMPORT_OPEN_DUMP (37349902L) #define IMPORT_IMPORT (37349903L) #define IMPORT_TTY (37349904L) #define IMPORT_RENAME_OPEN (37349905L) #define IMPORT_RENAME_LOCK (37349906L) #define IMPORT_RENAME_UNLOCK (37349907L) #define IMPORT_RENAME_CLOSE (37349908L) #define IMPORT_SINGLE_RECORD (37349909L) #define IMPORT_PLURAL_RECORDS (37349910L) #define IMPORT_GET_PARAMS (37349911L) #define ERROR_TABLE_BASE_imp (37349888L) extern const struct error_table et_imp_error_table; #if !defined(_WIN32) /* for compatibility with older versions... */ extern void initialize_imp_error_table (void) /*@modifies internalState@*/; #else #define initialize_imp_error_table() #endif #if !defined(_WIN32) #define init_imp_err_tbl initialize_imp_error_table #define imp_err_base ERROR_TABLE_BASE_imp #endif /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _IPROP_H_RPCGEN #define _IPROP_H_RPCGEN #include typedef struct { u_int utf8str_t_len; char *utf8str_t_val; } utf8str_t; typedef uint32_t kdb_sno_t; struct kdbe_time_t { uint32_t seconds; uint32_t useconds; }; typedef struct kdbe_time_t kdbe_time_t; struct kdbe_key_t { int32_t k_ver; int32_t k_kvno; struct { u_int k_enctype_len; int32_t *k_enctype_val; } k_enctype; struct { u_int k_contents_len; utf8str_t *k_contents_val; } k_contents; }; typedef struct kdbe_key_t kdbe_key_t; struct kdbe_data_t { int32_t k_magic; utf8str_t k_data; }; typedef struct kdbe_data_t kdbe_data_t; struct kdbe_princ_t { utf8str_t k_realm; struct { u_int k_components_len; kdbe_data_t *k_components_val; } k_components; int32_t k_nametype; }; typedef struct kdbe_princ_t kdbe_princ_t; struct kdbe_tl_t { int16_t tl_type; struct { u_int tl_data_len; char *tl_data_val; } tl_data; }; typedef struct kdbe_tl_t kdbe_tl_t; typedef struct { u_int kdbe_pw_hist_t_len; kdbe_key_t *kdbe_pw_hist_t_val; } kdbe_pw_hist_t; enum kdbe_attr_type_t { AT_ATTRFLAGS = 0, AT_MAX_LIFE = 1, AT_MAX_RENEW_LIFE = 2, AT_EXP = 3, AT_PW_EXP = 4, AT_LAST_SUCCESS = 5, AT_LAST_FAILED = 6, AT_FAIL_AUTH_COUNT = 7, AT_PRINC = 8, AT_KEYDATA = 9, AT_TL_DATA = 10, AT_LEN = 11, AT_MOD_PRINC = 12, AT_MOD_TIME = 13, AT_MOD_WHERE = 14, AT_PW_LAST_CHANGE = 15, AT_PW_POLICY = 16, AT_PW_POLICY_SWITCH = 17, AT_PW_HIST_KVNO = 18, AT_PW_HIST = 19 }; typedef enum kdbe_attr_type_t kdbe_attr_type_t; struct kdbe_val_t { kdbe_attr_type_t av_type; union { uint32_t av_attrflags; uint32_t av_max_life; uint32_t av_max_renew_life; uint32_t av_exp; uint32_t av_pw_exp; uint32_t av_last_success; uint32_t av_last_failed; uint32_t av_fail_auth_count; kdbe_princ_t av_princ; struct { u_int av_keydata_len; kdbe_key_t *av_keydata_val; } av_keydata; struct { u_int av_tldata_len; kdbe_tl_t *av_tldata_val; } av_tldata; int16_t av_len; uint32_t av_pw_last_change; kdbe_princ_t av_mod_princ; uint32_t av_mod_time; utf8str_t av_mod_where; utf8str_t av_pw_policy; bool_t av_pw_policy_switch; uint32_t av_pw_hist_kvno; struct { u_int av_pw_hist_len; kdbe_pw_hist_t *av_pw_hist_val; } av_pw_hist; struct { u_int av_extension_len; char *av_extension_val; } av_extension; } kdbe_val_t_u; }; typedef struct kdbe_val_t kdbe_val_t; typedef struct { u_int kdbe_t_len; kdbe_val_t *kdbe_t_val; } kdbe_t; struct kdb_incr_update_t { utf8str_t kdb_princ_name; kdb_sno_t kdb_entry_sno; kdbe_time_t kdb_time; kdbe_t kdb_update; bool_t kdb_deleted; bool_t kdb_commit; struct { u_int kdb_kdcs_seen_by_len; utf8str_t *kdb_kdcs_seen_by_val; } kdb_kdcs_seen_by; struct { u_int kdb_futures_len; char *kdb_futures_val; } kdb_futures; }; typedef struct kdb_incr_update_t kdb_incr_update_t; typedef struct { u_int kdb_ulog_t_len; kdb_incr_update_t *kdb_ulog_t_val; } kdb_ulog_t; enum update_status_t { UPDATE_OK = 0, UPDATE_ERROR = 1, UPDATE_FULL_RESYNC_NEEDED = 2, UPDATE_BUSY = 3, UPDATE_NIL = 4, UPDATE_PERM_DENIED = 5 }; typedef enum update_status_t update_status_t; struct kdb_last_t { kdb_sno_t last_sno; kdbe_time_t last_time; }; typedef struct kdb_last_t kdb_last_t; struct kdb_incr_result_t { kdb_last_t lastentry; kdb_ulog_t updates; update_status_t ret; }; typedef struct kdb_incr_result_t kdb_incr_result_t; struct kdb_fullresync_result_t { kdb_last_t lastentry; update_status_t ret; }; typedef struct kdb_fullresync_result_t kdb_fullresync_result_t; #define KRB5_IPROP_PROG 100423 #define KRB5_IPROP_VERS 1 #define IPROP_NULL 0 extern void * iprop_null_1(); #define IPROP_GET_UPDATES 1 extern kdb_incr_result_t * iprop_get_updates_1(); #define IPROP_FULL_RESYNC 2 extern kdb_fullresync_result_t * iprop_full_resync_1(); extern int krb5_iprop_prog_1_freeresult(); /* the xdr functions */ extern bool_t xdr_utf8str_t(); extern bool_t xdr_kdb_sno_t(); extern bool_t xdr_kdbe_time_t(); extern bool_t xdr_kdbe_key_t(); extern bool_t xdr_kdbe_data_t(); extern bool_t xdr_kdbe_princ_t(); extern bool_t xdr_kdbe_tl_t(); extern bool_t xdr_kdbe_pw_hist_t(); extern bool_t xdr_kdbe_attr_type_t(); extern bool_t xdr_kdbe_val_t(); extern bool_t xdr_kdbe_t(); extern bool_t xdr_kdb_incr_update_t(); extern bool_t xdr_kdb_ulog_t(); extern bool_t xdr_update_status_t(); extern bool_t xdr_kdb_last_t(); extern bool_t xdr_kdb_incr_result_t(); extern bool_t xdr_kdb_fullresync_result_t(); #endif /* !_IPROP_H_RPCGEN */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. * * $Id: kadm5_create.c,v 1.6 1998/10/30 02:52:37 marc Exp $ * $Source: /cvs/krbdev/krb5/src/kadmin/dbutil/kadm5_create.c,v $ */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * 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 FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "string_table.h" #include #include #include #include #include #include #include #include #include #include "kdb5_util.h" #include int add_admin_old_princ(void *handle, krb5_context context, char *name, char *realm, int attrs, int lifetime); int add_admin_sname_princ(void *handle, krb5_context context, char *sname, int attrs, int lifetime); static int add_admin_princ(void *handle, krb5_context context, krb5_principal principal, int attrs, int lifetime); static int add_admin_princs(void *handle, krb5_context context, char *realm); #define ERR 1 #define OK 0 #define ADMIN_LIFETIME 60*60*3 /* 3 hours */ #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ extern char *progname; /* * Function: kadm5_create * * Purpose: create admin principals in KDC database * * Arguments: params (r) configuration parameters to use * * Effects: Creates KADM5_ADMIN_SERVICE and KADM5_CHANGEPW_SERVICE * principals in the KDC database and sets their attributes * appropriately. */ int kadm5_create(kadm5_config_params *params) { int retval; krb5_context context; kadm5_config_params lparams; if ((retval = kadm5_init_krb5_context(&context))) exit(ERR); (void) memset(&lparams, 0, sizeof (kadm5_config_params)); /* * The lock file has to exist before calling kadm5_init, but * params->admin_lockfile may not be set yet... */ if ((retval = kadm5_get_config_params(context, 1, params, &lparams))) { com_err(progname, retval, gettext("while looking up the Kerberos configuration")); return 1; } retval = kadm5_create_magic_princs(&lparams, context); kadm5_free_config_params(context, &lparams); krb5_free_context(context); return retval; } int kadm5_create_magic_princs(kadm5_config_params *params, krb5_context context) { int retval; void *handle; retval = krb5_klog_init(context, "admin_server", progname, 0); if (retval) return retval; if ((retval = kadm5_init(progname, NULL, NULL, params, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, db5util_db_args, &handle))) { com_err(progname, retval, gettext("while initializing the Kerberos admin interface")); return retval; } retval = add_admin_princs(handle, context, params->realm); kadm5_destroy(handle); krb5_klog_close(context); return retval; } /* * Function: build_name_with_realm * * Purpose: concatenate a name and a realm to form a krb5 name * * Arguments: * * name (input) the name * realm (input) the realm * * Returns: * * pointer to name@realm, in allocated memory, or NULL if it * cannot be allocated * * Requires: both strings are null-terminated */ static char *build_name_with_realm(char *name, char *realm) { char *n; n = (char *) malloc(strlen(name) + strlen(realm) + 2); sprintf(n, "%s@%s", name, realm); return n; } /* * Function: add_admin_princs * * Purpose: create admin principals * * Arguments: * * rseed (input) random seed * realm (input) realm, or NULL for default realm * (output) status, 0 for success, 1 for serious error * * Requires: * * Effects: * * add_admin_princs creates KADM5_ADMIN_SERVICE, * KADM5_CHANGEPW_SERVICE. If any of these exist a message is * printed. If any of these existing principal do not have the proper * attributes, a warning message is printed. */ static int add_admin_princs(void *handle, krb5_context context, char *realm) { krb5_error_code ret = 0; /* * Solaris Kerberos: * The kadmin/admin principal is unused on Solaris. This principal is used * in AUTH_GSSAPI but Solaris doesn't support AUTH_GSSAPI. RPCSEC_GSS can only * be used with host-based principals. * */ #if 0 if ((ret = add_admin_old_princ(handle, context, KADM5_ADMIN_SERVICE, realm, KRB5_KDB_DISALLOW_TGT_BASED, ADMIN_LIFETIME))) goto clean_and_exit; #endif if ((ret = add_admin_old_princ(handle, context, KADM5_CHANGEPW_SERVICE, realm, KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE, CHANGEPW_LIFETIME))) goto clean_and_exit; if ((ret = add_admin_sname_princ(handle, context, KADM5_ADMIN_HOST_SERVICE, KRB5_KDB_DISALLOW_TGT_BASED, ADMIN_LIFETIME))) goto clean_and_exit; if ((ret = add_admin_sname_princ(handle, context, KADM5_CHANGEPW_HOST_SERVICE, KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE, ADMIN_LIFETIME))) goto clean_and_exit; if ((ret = add_admin_sname_princ(handle, context, KADM5_KIPROP_HOST_SERVICE, KRB5_KDB_DISALLOW_TGT_BASED, ADMIN_LIFETIME))) goto clean_and_exit; clean_and_exit: return ret; } /* * Function: add_admin_princ * * Arguments: * * creator (r) principal to use as "mod_by" * rseed (r) seed for random key generator * principal (r) kerberos principal to add * attrs (r) principal's attributes * lifetime (r) principal's max life, or 0 * not_unique (r) error message for multiple entries, never used * exists (r) warning message for principal exists * wrong_attrs (r) warning message for wrong attributes * * Returns: * * OK on success * ERR on serious errors * * Effects: * * If the principal is not unique, not_unique is printed (but this * never happens). If the principal exists, then exists is printed * and if the principals attributes != attrs, wrong_attrs is printed. * Otherwise, the principal is created with mod_by creator and * attributes attrs and max life of lifetime (if not zero). */ static int add_admin_princ(void *handle, krb5_context context, krb5_principal principal, int attrs, int lifetime) { char *fullname; krb5_error_code ret; kadm5_principal_ent_rec ent; memset(&ent, 0, sizeof(ent)); if (krb5_unparse_name(context, principal, &fullname)) return ERR; ent.principal = principal; ent.max_life = lifetime; ent.attributes = attrs | KRB5_KDB_DISALLOW_ALL_TIX; ret = kadm5_create_principal(handle, &ent, (KADM5_PRINCIPAL | KADM5_MAX_LIFE | KADM5_ATTRIBUTES), "to-be-random"); if (ret) { if (ret != KADM5_DUP) { com_err(progname, ret, gettext(str_PUT_PRINC), fullname); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } } else { /* only randomize key if we created the principal */ /* * Solaris Kerberos: * Create kadmind principals with keys for all supported encryption types. * Follows a similar pattern to add_principal() in keytab.c. */ krb5_enctype *tmpenc, *enctype = NULL; krb5_key_salt_tuple *keysalt; int num_ks, i; krb5_int32 normalsalttype; ret = krb5_get_permitted_enctypes(context, &enctype); if (ret || *enctype == 0) { com_err(progname, ret, gettext("while getting list of permitted encryption types")); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } /* Count the number of enc types */ for (tmpenc = enctype, num_ks = 0; *tmpenc; tmpenc++) num_ks++; keysalt = malloc (sizeof (krb5_key_salt_tuple) * num_ks); if (keysalt == NULL) { com_err(progname, ENOMEM, gettext("while generating list of key salt tuples")); krb5_free_ktypes(context, enctype); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } ret = krb5_string_to_salttype("normal", &normalsalttype); if (ret) { com_err(progname, ret, gettext("while converting \"normal\" to a salttype")); free(keysalt); krb5_free_ktypes(context, enctype); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } /* Only create keys with "normal" salttype */ for (i = 0; i < num_ks; i++) { keysalt[i].ks_enctype = enctype[i]; keysalt[i].ks_salttype = normalsalttype; } ret = kadm5_randkey_principal_3(handle, ent.principal, FALSE, num_ks, keysalt, NULL, NULL); free(keysalt); krb5_free_ktypes (context, enctype); if (ret) { com_err(progname, ret, gettext(str_RANDOM_KEY), fullname); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } ent.attributes = attrs; ret = kadm5_modify_principal(handle, &ent, KADM5_ATTRIBUTES); if (ret) { com_err(progname, ret, gettext(str_PUT_PRINC), fullname); krb5_free_principal(context, ent.principal); free(fullname); return ERR; } } krb5_free_principal(context, ent.principal); free(fullname); return OK; } int add_admin_old_princ(void *handle, krb5_context context, char *name, char *realm, int attrs, int lifetime) { char *fullname; krb5_error_code ret; krb5_principal principal; fullname = build_name_with_realm(name, realm); if (ret = krb5_parse_name(context, fullname, &principal)) { com_err(progname, ret, gettext(str_PARSE_NAME)); return (ERR); } return (add_admin_princ(handle, context, principal, attrs, lifetime)); } int add_admin_sname_princ(void *handle, krb5_context context, char *sname, int attrs, int lifetime) { krb5_error_code ret; krb5_principal principal; if (ret = krb5_sname_to_principal(context, NULL, sname, KRB5_NT_SRV_HST, &principal)) { com_err(progname, ret, gettext("Could not get host based " "service name for %s principal\n"), sname); return (ERR); } return (add_admin_princ(handle, context, principal, attrs, lifetime)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * admin/create/kdb5_create.c * * Copyright 1990,1991 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. * * * Generate (from scratch) a Kerberos KDC database. */ /* * Yes, I know this is a hack, but we need admin.h without including the * rpc.h header. Additionally, our rpc.h header brings in * a des.h header which causes other problems. */ #define _RPC_RPC_H #include #include #include #include #include #include #include #include #include "kdb5_util.h" enum ap_op { NULL_KEY, /* setup null keys */ MASTER_KEY, /* use master key as new key */ TGT_KEY /* special handling for tgt key */ }; krb5_key_salt_tuple def_kslist = { ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL }; struct realm_info { krb5_deltat max_life; krb5_deltat max_rlife; krb5_timestamp expiration; krb5_flags flags; krb5_keyblock *key; krb5_int32 nkslist; krb5_key_salt_tuple *kslist; } rblock = { /* XXX */ KRB5_KDB_MAX_LIFE, KRB5_KDB_MAX_RLIFE, KRB5_KDB_EXPIRATION, KRB5_KDB_DEF_FLAGS, (krb5_keyblock *) NULL, 1, &def_kslist }; struct iterate_args { krb5_context ctx; struct realm_info *rblock; krb5_db_entry *dbentp; }; static krb5_error_code add_principal (krb5_context, krb5_principal, enum ap_op, struct realm_info *, krb5_keyblock *); /* * Steps in creating a database: * * 1) use the db calls to open/create a new database * * 2) get a realm name for the new db * * 3) get a master password for the new db; convert to an encryption key. * * 4) create various required entries in the database * * 5) close & exit */ extern krb5_principal master_princ; krb5_data tgt_princ_entries[] = { {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME}, {0, 0, 0} }; krb5_data db_creator_entries[] = { {0, sizeof("db_creation")-1, "db_creation"} }; /* XXX knows about contents of krb5_principal, and that tgt names are of form TGT/REALM@REALM */ krb5_principal_data tgt_princ = { 0, /* magic number */ {0, 0, 0}, /* krb5_data realm */ tgt_princ_entries, /* krb5_data *data */ 2, /* int length */ KRB5_NT_SRV_INST /* int type */ }; krb5_principal_data db_create_princ = { 0, /* magic number */ {0, 0, 0}, /* krb5_data realm */ db_creator_entries, /* krb5_data *data */ 1, /* int length */ KRB5_NT_SRV_INST /* int type */ }; extern char *mkey_password; extern char *progname; extern int exit_status; extern kadm5_config_params global_params; extern krb5_context util_context; void kdb5_create(argc, argv) int argc; char *argv[]; { int optchar; krb5_error_code retval; char *mkey_fullname; char *pw_str = 0; unsigned int pw_size = 0; int do_stash = 0; krb5_data pwd, seed; kdb_log_context *log_ctx; krb5_keyblock mkey; krb5_data master_salt = { 0 }; /* Solaris Kerberos */ (void) memset(&mkey, 0, sizeof (mkey)); /* Solaris Kerberos */ #if 0 if (strrchr(argv[0], '/')) argv[0] = strrchr(argv[0], '/')+1; #endif while ((optchar = getopt(argc, argv, "s")) != -1) { switch(optchar) { case 's': do_stash++; break; case 'h': if (!add_db_arg("hash=true")) { com_err(progname, ENOMEM, "while parsing command arguments\n"); exit(1); } break; case '?': default: usage(); return; } } rblock.max_life = global_params.max_life; rblock.max_rlife = global_params.max_rlife; rblock.expiration = global_params.expiration; rblock.flags = global_params.flags; rblock.nkslist = global_params.num_keysalts; rblock.kslist = global_params.keysalts; log_ctx = util_context->kdblog_context; /* SUNW14resync XXX */ #if 0 printf ("Loading random data\n"); retval = krb5_c_random_os_entropy (util_context, 1, NULL); if (retval) { /* Solaris Kerberos */ com_err (progname, retval, "Loading random data"); exit_status++; return; } #endif /* assemble & parse the master key name */ if ((retval = krb5_db_setup_mkey_name(util_context, global_params.mkey_name, global_params.realm, &mkey_fullname, &master_princ))) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while setting up master key name")); exit_status++; return; } krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm); krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm)); krb5_princ_set_realm_data(util_context, &tgt_princ, global_params.realm); krb5_princ_set_realm_length(util_context, &tgt_princ, strlen(global_params.realm)); krb5_princ_component(util_context, &tgt_princ,1)->data = global_params.realm; krb5_princ_component(util_context, &tgt_princ,1)->length = strlen(global_params.realm); printf(gettext("Initializing database '%s' for realm '%s',\n" "master key name '%s'\n"), global_params.dbname, global_params.realm, mkey_fullname); if (!mkey_password) { printf(gettext("You will be prompted for the " "database Master Password.\n")); printf(gettext("It is important that you NOT FORGET this password.\n")); fflush(stdout); pw_size = 1024; pw_str = malloc(pw_size); retval = krb5_read_password(util_context, gettext("Enter KDC database master key"), gettext("Re-enter KDC database " "master key to verify"), pw_str, &pw_size); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while reading master key from keyboard")); exit_status++; return; } mkey_password = pw_str; } pwd.data = mkey_password; pwd.length = strlen(mkey_password); retval = krb5_principal2salt(util_context, master_princ, &master_salt); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while calculated master key salt")); exit_status++; goto cleanup; } retval = krb5_c_string_to_key(util_context, global_params.enctype, &pwd, &master_salt, &mkey); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while transforming master key from password")); exit_status++; goto cleanup; } retval = krb5_copy_keyblock(util_context, &mkey, &rblock.key); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while copying master key")); exit_status++; goto cleanup; } seed.length = mkey.length; seed.data = (char *)mkey.contents; if ((retval = krb5_c_random_seed(util_context, &seed))) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while initializing random key generator")); exit_status++; goto cleanup; } if ((retval = krb5_db_create(util_context, db5util_db_args))) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while creating database '%s'"), global_params.dbname); exit_status++; goto cleanup; } #if 0 /************** Begin IFDEF'ed OUT *******************************/ if (retval = krb5_db_fini(util_context)) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while closing current database")); exit_status++; goto cleanup; } if ((retval = krb5_db_set_name(util_context, global_params.dbname))) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while setting active database to '%s'"), global_params.dbname); exit_status++; goto cleanup; } if ((retval = krb5_db_init(util_context))) { com_err(progname, retval, gettext("while initializing the database '%s'"), global_params.dbname); exit_status++; goto cleanup; } #endif /**************** END IFDEF'ed OUT *******************************/ /* Solaris Kerberos: for iprop */ if (log_ctx && log_ctx->iproprole) { if (retval = ulog_map(util_context, &global_params, FKCOMMAND)) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while creating update log")); exit_status++; goto cleanup; } /* * We're reinitializing the update log in case one already * existed, but this should never happen. */ (void) memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t)); log_ctx->ulog->kdb_hmagic = KDB_HMAGIC; log_ctx->ulog->db_version_num = KDB_VERSION; log_ctx->ulog->kdb_state = KDB_STABLE; log_ctx->ulog->kdb_block = ULOG_BLOCK; /* * Since we're creating a new db we shouldn't worry about * adding the initial principals since any slave might as well * do full resyncs from this newly created db. */ log_ctx->iproprole = IPROP_NULL; } if ((retval = add_principal(util_context, master_princ, MASTER_KEY, &rblock, &mkey)) || (retval = add_principal(util_context, &tgt_princ, TGT_KEY, &rblock, &mkey))) { (void) krb5_db_fini(util_context); /* Solaris Kerberos */ com_err(progname, retval, gettext("while adding entries to the database")); exit_status++; goto cleanup; } /* * Always stash the master key so kadm5_create does not prompt for * it; delete the file below if it was not requested. DO NOT EXIT * BEFORE DELETING THE KEYFILE if do_stash is not set. */ retval = krb5_db_store_master_key(util_context, global_params.stash_file, master_princ, &mkey, mkey_password); if (retval) { /* Solaris Kerberos */ com_err(progname, errno, gettext("while storing key")); printf(gettext("Warning: couldn't stash master key.\n")); } if (pw_str) memset(pw_str, 0, pw_size); if (kadm5_create(&global_params)) { if (!do_stash) unlink(global_params.stash_file); exit_status++; goto cleanup; } if (!do_stash) unlink(global_params.stash_file); /* Solaris Kerberos: deal with master_keyblock in better way */ cleanup: if (pw_str) { if (mkey_password == pw_str) mkey_password = NULL; free(pw_str); } if (master_salt.data) free(master_salt.data); krb5_free_keyblock(util_context, rblock.key); krb5_free_keyblock_contents(util_context, &mkey); (void) krb5_db_fini(util_context); return; } static krb5_error_code tgt_keysalt_iterate(ksent, ptr) krb5_key_salt_tuple *ksent; krb5_pointer ptr; { krb5_context context; krb5_error_code kret; struct iterate_args *iargs; krb5_keyblock key; krb5_int32 ind; krb5_data pwd; iargs = (struct iterate_args *) ptr; kret = 0; context = iargs->ctx; /* * Convert the master key password into a key for this particular * encryption system. */ pwd.data = mkey_password; pwd.length = strlen(mkey_password); kret = krb5_c_random_seed(context, &pwd); if (kret) return kret; if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) { ind = iargs->dbentp->n_key_data-1; if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype, &key))) { kret = krb5_dbekd_encrypt_key_data(context, iargs->rblock->key, &key, NULL, 1, &iargs->dbentp->key_data[ind]); krb5_free_keyblock_contents(context, &key); } } return(kret); } static krb5_error_code add_principal(context, princ, op, pblock, mkey) krb5_context context; krb5_principal princ; enum ap_op op; struct realm_info *pblock; krb5_keyblock *mkey; { krb5_error_code retval; krb5_db_entry entry; krb5_timestamp now; struct iterate_args iargs; int nentries = 1; memset((char *) &entry, 0, sizeof(entry)); entry.len = KRB5_KDB_V1_BASE_LENGTH; entry.attributes = pblock->flags; entry.max_life = pblock->max_life; entry.max_renewable_life = pblock->max_rlife; entry.expiration = pblock->expiration; if ((retval = krb5_copy_principal(context, princ, &entry.princ))) goto error_out; if ((retval = krb5_timeofday(context, &now))) goto error_out; if ((retval = krb5_dbe_update_mod_princ_data(context, &entry, now, &db_create_princ))) goto error_out; switch (op) { case MASTER_KEY: if ((entry.key_data=(krb5_key_data*)malloc(sizeof(krb5_key_data))) == NULL) goto error_out; memset((char *) entry.key_data, 0, sizeof(krb5_key_data)); entry.n_key_data = 1; entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->key, mkey, NULL, 1, entry.key_data))) goto error_out; break; case TGT_KEY: iargs.ctx = context; iargs.rblock = pblock; iargs.dbentp = &entry; /* * Iterate through the key/salt list, ignoring salt types. */ if ((retval = krb5_keysalt_iterate(pblock->kslist, pblock->nkslist, 1, tgt_keysalt_iterate, (krb5_pointer) &iargs))) return retval; break; case NULL_KEY: return EOPNOTSUPP; default: break; } entry.mask = (KADM5_KEY_DATA | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_TL_DATA | KADM5_PRINC_EXPIRE_TIME); retval = krb5_db_put_principal(context, &entry, &nentries); error_out:; krb5_db_free_principal(context, &entry, 1); return retval; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * admin/destroy/kdb5_destroy.c * * Copyright 1990 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. * * * kdb_dest(roy): destroy the named database. * * This version knows about DBM format databases. */ #include "k5-int.h" #include #include "com_err.h" #include #include #include #include "kdb5_util.h" extern int exit_status; extern krb5_boolean dbactive; extern kadm5_config_params global_params; void kdb5_destroy(argc, argv) int argc; char *argv[]; { extern char *optarg; extern int optind; int optchar; char *dbname; char buf[5]; krb5_error_code retval1; krb5_context context; int force = 0; char ufilename[MAX_FILENAME]; retval1 = kadm5_init_krb5_context(&context); if( retval1 ) { /* Solaris Kerberos */ com_err(progname, retval1, "while initializing krb5_context"); exit(1); } if ((retval1 = krb5_set_default_realm(context, util_context->default_realm))) { /* Solaris Kerberos */ com_err(progname, retval1, "while setting default realm name"); exit(1); } /* Solaris Kerberos */ #if 0 if (strrchr(argv[0], '/')) argv[0] = strrchr(argv[0], '/')+1; #endif dbname = global_params.dbname; optind = 1; while ((optchar = getopt(argc, argv, "f")) != -1) { switch(optchar) { case 'f': force++; break; case '?': default: usage(); return; /*NOTREACHED*/ } } if (!force) { printf(gettext("Deleting KDC database stored in '%s', " "are you sure?\n"), dbname); printf(gettext("(type 'yes' or 'y' to confirm)? ")); if (fgets(buf, sizeof(buf), stdin) == NULL) { exit_status++; return; } if ((strncmp(buf, gettext("yes\n"), strlen(gettext("yes\n"))) != 0) && (strncmp(buf, gettext("y\n"), strlen(gettext("y\n"))) != 0)) { printf(gettext("database not deleted !! '%s'...\n"), dbname); exit_status++; return; } printf(gettext("OK, deleting database '%s'...\n"), dbname); } retval1 = krb5_db_destroy(context, db5util_db_args); /* check for a stash file and delete it if necessary */ if (global_params.stash_file == NULL) { char stash[MAXPATHLEN+1]; extern krb5_principal master_princ; krb5_data *realm = krb5_princ_realm(context, master_princ); (void) strlcpy(stash, DEFAULT_KEYFILE_STUB, sizeof (stash)); /* * realm->data is not necessarily NULL terminated so be * careful how much data is copied here. Don't overrun * the "stash" buffer and dont overrun the realm->data buffer, * copy the smaller of the 2 lengths. */ (void) strncat(stash, realm->data, (realm->length < (MAXPATHLEN-strlen(stash)) ? realm->length : MAXPATHLEN-strlen(stash))); global_params.stash_file = (char *)strdup(stash); } if (!access(global_params.stash_file, F_OK)) (void)unlink(global_params.stash_file); if (retval1) { /* Solaris Kerberos */ com_err(progname, retval1, gettext("deleting database '%s'"), dbname); exit_status++; return; } if (global_params.iprop_enabled) { if (strlcpy(ufilename, dbname, MAX_FILENAME) >= MAX_FILENAME) { exit_status++; return; } if (strlcat(ufilename, ".ulog", MAX_FILENAME) >= MAX_FILENAME) { exit_status++; return; } (void) unlink(ufilename); } dbactive = FALSE; printf(gettext("** Database '%s' destroyed.\n"), dbname); return; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * admin/stash/kdb5_stash.c * * Copyright 1990 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. * * * Store the master database key in a file. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * 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 FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include #include "com_err.h" #include #include #include #include "kdb5_util.h" extern krb5_principal master_princ; extern kadm5_config_params global_params; extern int exit_status; void kdb5_stash(argc, argv) int argc; char *argv[]; { extern char *optarg; extern int optind; int optchar; krb5_error_code retval; char *dbname = (char *) NULL; char *realm = 0; char *mkey_name = 0; char *mkey_fullname; char *keyfile = 0; krb5_context context; krb5_keyblock mkey; /* Solaris Kerberos */ #if 0 if (strrchr(argv[0], '/')) argv[0] = strrchr(argv[0], '/')+1; #endif retval = kadm5_init_krb5_context(&context); if( retval ) { /* Solaris Kerberos */ com_err(progname, retval, "while initializing krb5_context"); exit(1); } if ((retval = krb5_set_default_realm(context, util_context->default_realm))) { /* Solaris Kerberos */ com_err(progname, retval, "while setting default realm name"); exit(1); } dbname = global_params.dbname; realm = global_params.realm; mkey_name = global_params.mkey_name; keyfile = global_params.stash_file; optind = 1; while ((optchar = getopt(argc, argv, "f:")) != -1) { switch(optchar) { case 'f': keyfile = optarg; break; case '?': default: usage(); return; } } if (!krb5_c_valid_enctype(global_params.enctype)) { char tmp[32]; if (krb5_enctype_to_string(global_params.enctype, tmp, sizeof (tmp))) /* Solaris Kerberos */ com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, gettext("while setting up enctype %d"), global_params.enctype); else { /* Solaris Kerberos */ com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, tmp); } exit_status++; return; } /* assemble & parse the master key name */ retval = krb5_db_setup_mkey_name(context, mkey_name, realm, &mkey_fullname, &master_princ); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while setting up master key name")); exit_status++; return; } retval = krb5_db_open(context, db5util_db_args, KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_OTHER); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while initializing the database '%s'"), dbname); exit_status++; return; } /* TRUE here means read the keyboard, but only once */ retval = krb5_db_fetch_mkey(context, master_princ, global_params.enctype, TRUE, FALSE, (char *) NULL, 0, &mkey); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while reading master key")); (void) krb5_db_fini(context); exit_status++; return; } retval = krb5_db_verify_master_key(context, master_princ, &mkey); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while verifying master key")); krb5_free_keyblock_contents(context, &mkey); (void) krb5_db_fini(context); exit_status++; return; } retval = krb5_db_store_master_key(context, keyfile, master_princ, &mkey, NULL); if (retval) { /* Solaris Kerberos */ com_err(progname, errno, gettext("while storing key")); krb5_free_keyblock_contents(context, &mkey); (void) krb5_db_fini(context); exit_status++; return; } krb5_free_keyblock_contents(context, &mkey); retval = krb5_db_fini(context); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("closing database '%s'"), dbname); exit_status++; return; } krb5_free_context(context); exit_status = 0; return; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * admin/edit/kdb5_edit.c * * (C) Copyright 1990,1991, 1996 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. * * * Edit a KDC database. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * 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 FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* * Yes, I know this is a hack, but we need admin.h without including the * rpc.h header. Additionally, our rpc.h header brings in * a des.h header which causes other problems. */ #define _RPC_RPC_H #include #include #include #include #include #include #include #include #include #include "kdb5_util.h" char *Err_no_master_msg = "Master key not entered!\n"; char *Err_no_database = "Database not currently opened!\n"; /* * XXX Ick, ick, ick. These global variables shouldn't be global.... */ char *mkey_password = 0; /* * I can't figure out any way for this not to be global, given how ss * works. */ int exit_status = 0; krb5_context util_context; kadm5_config_params global_params; void usage() { fprintf(stderr, "%s: " "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n" "\t [-sf stashfilename] [-P password] [-m] cmd [cmd_options]\n" "\tcreate [-s]\n" "\tdestroy [-f]\n" "\tstash [-f keyfile]\n" "\tdump [-old] [-ov] [-b6] [-verbose] [filename [princs...]]\n" "\t [-mkey_convert] [-new_mkey_file mkey_file]\n" "\t [-rev] [-recurse] [filename [princs...]]\n" "\tload [-old] [-ov] [-b6] [-verbose] [-update] filename\n" "\tark [-e etype_list] principal\n" "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n" "\t\t\tLook at each database documentation for supported arguments\n", gettext("Usage")); exit(1); } krb5_keyblock master_key; extern krb5_principal master_princ; krb5_db_entry master_entry; int valid_master_key = 0; char *progname; krb5_boolean manual_mkey = FALSE; krb5_boolean dbactive = FALSE; static int open_db_and_mkey(void); static void add_random_key(int, char **); typedef void (*cmd_func)(int, char **); struct _cmd_table { char *name; cmd_func func; int opendb; } cmd_table[] = { {"create", kdb5_create, 0}, {"destroy", kdb5_destroy, 1}, {"stash", kdb5_stash, 1}, {"dump", dump_db, 1}, {"load", load_db, 0}, {"ark", add_random_key, 1}, {NULL, NULL, 0}, }; static struct _cmd_table *cmd_lookup(name) char *name; { struct _cmd_table *cmd = cmd_table; while (cmd->name) { if (strcmp(cmd->name, name) == 0) return cmd; else cmd++; } return NULL; } #define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL)) char **db5util_db_args = NULL; int db5util_db_args_size = 0; static void extended_com_err_fn (const char *myprog, errcode_t code, const char *fmt, va_list args) { const char *emsg; if (code) { emsg = krb5_get_error_message (util_context, code); fprintf (stderr, "%s: %s ", myprog, emsg); krb5_free_error_message (util_context, emsg); } else { fprintf (stderr, "%s: ", myprog); } vfprintf (stderr, fmt, args); fprintf (stderr, "\n"); } int add_db_arg(char *arg) { char **temp; db5util_db_args_size++; temp = realloc(db5util_db_args, sizeof(char *) * (db5util_db_args_size + 1)); if (temp == NULL) return 0; db5util_db_args = temp; db5util_db_args[db5util_db_args_size-1] = arg; db5util_db_args[db5util_db_args_size] = NULL; return 1; } int main(argc, argv) int argc; char *argv[]; { struct _cmd_table *cmd = NULL; char *koptarg, **cmd_argv; char *db_name_tmp = NULL; int cmd_argc; krb5_error_code retval; (void) setlocale(LC_ALL, ""); set_com_err_hook(extended_com_err_fn); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); Err_no_master_msg = gettext("Master key not entered!\n"); Err_no_database = gettext("Database not currently opened!\n"); /* * Solaris Kerberos: * Ensure that "progname" is set before calling com_err. */ progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0]); retval = kadm5_init_krb5_context(&util_context); if (retval) { com_err (progname, retval, gettext("while initializing Kerberos code")); exit(1); } cmd_argv = (char **) malloc(sizeof(char *)*argc); if (cmd_argv == NULL) { com_err(progname, ENOMEM, gettext("while creating sub-command arguments")); exit(1); } memset(cmd_argv, 0, sizeof(char *)*argc); cmd_argc = 1; argv++; argc--; while (*argv) { if (strcmp(*argv, "-P") == 0 && ARG_VAL) { mkey_password = koptarg; manual_mkey = TRUE; } else if (strcmp(*argv, "-d") == 0 && ARG_VAL) { global_params.dbname = koptarg; global_params.mask |= KADM5_CONFIG_DBNAME; db_name_tmp = malloc( strlen(global_params.dbname) + sizeof("dbname=")); if( db_name_tmp == NULL ) { com_err(progname, ENOMEM, "while parsing command arguments"); exit(1); } strcpy( db_name_tmp, "dbname="); strcat( db_name_tmp, global_params.dbname ); if (!add_db_arg(db_name_tmp)) { com_err(progname, ENOMEM, "while parsing command arguments\n"); exit(1); } } else if (strcmp(*argv, "-x") == 0 && ARG_VAL) { if (!add_db_arg(koptarg)) { com_err(progname, ENOMEM, "while parsing command arguments\n"); exit(1); } } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) { global_params.realm = koptarg; global_params.mask |= KADM5_CONFIG_REALM; /* not sure this is really necessary */ if ((retval = krb5_set_default_realm(util_context, global_params.realm))) { com_err(progname, retval, gettext("while setting default " "realm name")); exit(1); } } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) { if (krb5_string_to_enctype(koptarg, &global_params.enctype)) { /* Solaris Kerberos */ com_err(progname, 0, gettext("%s is an invalid enctype"), koptarg); } else global_params.mask |= KADM5_CONFIG_ENCTYPE; } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) { global_params.mkey_name = koptarg; global_params.mask |= KADM5_CONFIG_MKEY_NAME; } else if (((strcmp(*argv, "-sf") == 0) /* SUNWresync121 - carry the old -f forward too */ || (strcmp(*argv, "-f") == 0)) && ARG_VAL) { global_params.stash_file = koptarg; global_params.mask |= KADM5_CONFIG_STASH_FILE; } else if (strcmp(*argv, "-m") == 0) { manual_mkey = TRUE; global_params.mkey_from_kbd = 1; global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; } else if (cmd_lookup(*argv) != NULL) { if (cmd_argv[0] == NULL) cmd_argv[0] = *argv; else usage(); } else { cmd_argv[cmd_argc++] = *argv; } argv++; argc--; } if (cmd_argv[0] == NULL) usage(); if( !util_context->default_realm ) { char *temp = NULL; retval = krb5_get_default_realm(util_context, &temp); if( retval ) { com_err (progname, retval, "while getting default realm"); exit(1); } util_context->default_realm = temp; } retval = kadm5_get_config_params(util_context, 1, &global_params, &global_params); if (retval) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while retreiving configuration parameters")); exit(1); } /* * Dump creates files which should not be world-readable. It is * easiest to do a single umask call here. */ (void) umask(077); (void) memset(&master_key, 0, sizeof (krb5_keyblock)); if ((global_params.enctype != ENCTYPE_UNKNOWN) && (!krb5_c_valid_enctype(global_params.enctype))) { /* Solaris Kerberos */ com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, gettext("while setting up enctype %d"), global_params.enctype); exit(1); } cmd = cmd_lookup(cmd_argv[0]); if (cmd->opendb && open_db_and_mkey()) return exit_status; if (global_params.iprop_enabled == TRUE) ulog_set_role(util_context, IPROP_MASTER); else ulog_set_role(util_context, IPROP_NULL); (*cmd->func)(cmd_argc, cmd_argv); if( db_name_tmp ) free( db_name_tmp ); if( db5util_db_args ) free(db5util_db_args); kadm5_free_config_params(util_context, &global_params); krb5_free_context(util_context); return exit_status; } #if 0 /* * This function is no longer used in kdb5_util (and it would no * longer work, anyway). */ void set_dbname(argc, argv) int argc; char *argv[]; { krb5_error_code retval; if (argc < 3) { /* Solaris Kerberos */ com_err(progname, 0, gettext("Too few arguments")); com_err(progname, 0, gettext("Usage: %s dbpathname realmname"), progname); exit_status++; return; } if (dbactive) { if ((retval = krb5_db_fini(util_context)) && retval!= KRB5_KDB_DBNOTINITED) { /* Solaris Kerberos */ com_err(progname, retval, gettext("while closing previous database")); exit_status++; return; } if (valid_master_key) { krb5_free_keyblock_contents(util_context, &master_key); master_key.contents = NULL; valid_master_key = 0; } krb5_free_principal(util_context, master_princ); dbactive = FALSE; } /* Solaris Kerberos */ (void) set_dbname_help(progname, argv[1]); return; } #endif /* * open_db_and_mkey: Opens the KDC and policy database, and sets the * global master_* variables. Sets dbactive to TRUE if the databases * are opened, and valid_master_key to 1 if the global master * variables are set properly. Returns 0 on success, and 1 on * failure, but it is not considered a failure if the master key * cannot be fetched (the master key stash file may not exist when the * program is run). */ static int open_db_and_mkey() { krb5_error_code retval; int nentries; krb5_boolean more; krb5_data scratch, pwd, seed; dbactive = FALSE; valid_master_key = 0; if ((retval = krb5_db_open(util_context, db5util_db_args, KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) { com_err(progname, retval, "while initializing database"); exit_status++; return(1); } /* assemble & parse the master key name */ if ((retval = krb5_db_setup_mkey_name(util_context, global_params.mkey_name, global_params.realm, 0, &master_princ))) { com_err(progname, retval, gettext("while setting up master key name")); exit_status++; return(1); } nentries = 1; if ((retval = krb5_db_get_principal(util_context, master_princ, &master_entry, &nentries, &more))) { com_err(progname, retval, gettext("while retrieving master entry")); exit_status++; (void) krb5_db_fini(util_context); return(1); } else if (more) { com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, gettext("while retrieving master entry")); exit_status++; (void) krb5_db_fini(util_context); return(1); } else if (!nentries) { com_err(progname, KRB5_KDB_NOENTRY, gettext("while retrieving master entry")); exit_status++; (void) krb5_db_fini(util_context); return(1); } krb5_db_free_principal(util_context, &master_entry, nentries); /* the databases are now open, and the master principal exists */ dbactive = TRUE; if (mkey_password) { pwd.data = mkey_password; pwd.length = strlen(mkey_password); retval = krb5_principal2salt(util_context, master_princ, &scratch); if (retval) { com_err(progname, retval, gettext("while calculated master key salt")); /* Solaris Kerberos */ exit_status++; return(1); } /* If no encryption type is set, use the default */ if (global_params.enctype == ENCTYPE_UNKNOWN) { global_params.enctype = DEFAULT_KDC_ENCTYPE; if (!krb5_c_valid_enctype(global_params.enctype)) com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, gettext("while setting up enctype %d"), global_params.enctype); } retval = krb5_c_string_to_key(util_context, global_params.enctype, &pwd, &scratch, &master_key); if (retval) { com_err(progname, retval, gettext("while transforming master key from password")); /* Solaris Kerberos */ exit_status++; return(1); } free(scratch.data); mkey_password = 0; } else if ((retval = krb5_db_fetch_mkey(util_context, master_princ, global_params.enctype, manual_mkey, FALSE, global_params.stash_file, 0, &master_key))) { com_err(progname, retval, gettext("while reading master key")); com_err(progname, 0, gettext("Warning: proceeding without master key")); /* * Solaris Kerberos: We don't want to count as an error if for instance * the stash file is not present and we are trying to automate * propagation, which really doesn't need a master key to do so. */ if (retval != KRB5_KDB_CANTREAD_STORED) exit_status++; return(0); } if ((retval = krb5_db_verify_master_key(util_context, master_princ, &master_key))) { com_err(progname, retval, gettext("while verifying master key")); exit_status++; krb5_free_keyblock_contents(util_context, &master_key); return(1); } seed.length = master_key.length; seed.data = (char *)master_key.contents; if ((retval = krb5_c_random_seed(util_context, &seed))) { com_err(progname, retval, gettext("while initializing random key generator")); exit_status++; krb5_free_keyblock_contents(util_context, &master_key); return(1); } valid_master_key = 1; dbactive = TRUE; return 0; } #ifdef HAVE_GETCWD #undef getwd #endif int quit() { krb5_error_code retval; static krb5_boolean finished = 0; if (finished) return 0; retval = krb5_db_fini(util_context); krb5_free_keyblock_contents(util_context, &master_key); finished = TRUE; krb5_free_context(util_context); if (retval && retval != KRB5_KDB_DBNOTINITED) { com_err(progname, retval, gettext("while closing database")); exit_status++; return 1; } return 0; } static void add_random_key(argc, argv) int argc; char **argv; { krb5_error_code ret; krb5_principal princ; krb5_db_entry dbent; int n; krb5_boolean more; krb5_timestamp now; krb5_key_salt_tuple *keysalts = NULL; krb5_int32 num_keysalts = 0; int free_keysalts; /* Solaris Kerberos */ char *me = progname; char *ks_str = NULL; char *pr_str; if (argc < 2) usage(); for (argv++, argc--; *argv; argv++, argc--) { if (!strcmp(*argv, "-e")) { argv++; argc--; ks_str = *argv; continue; } else break; } if (argc < 1) usage(); pr_str = *argv; ret = krb5_parse_name(util_context, pr_str, &princ); if (ret) { com_err(me, ret, gettext("while parsing principal name %s"), pr_str); exit_status++; return; } n = 1; ret = krb5_db_get_principal(util_context, princ, &dbent, &n, &more); if (ret) { com_err(me, ret, gettext("while fetching principal %s"), pr_str); exit_status++; return; } if (n != 1) { fprintf(stderr, gettext("principal %s not found\n"), pr_str); exit_status++; return; } if (more) { fprintf(stderr, gettext("principal %s not unique\n"), pr_str); krb5_db_free_principal(util_context, &dbent, 1); exit_status++; return; } ret = krb5_string_to_keysalts(ks_str, ", \t", ":.-", 0, &keysalts, &num_keysalts); if (ret) { com_err(me, ret, gettext("while parsing keysalts %s"), ks_str); exit_status++; return; } if (!num_keysalts || keysalts == NULL) { num_keysalts = global_params.num_keysalts; keysalts = global_params.keysalts; free_keysalts = 0; } else free_keysalts = 1; ret = krb5_dbe_ark(util_context, &master_key, keysalts, num_keysalts, &dbent); if (free_keysalts) free(keysalts); if (ret) { com_err(me, ret, gettext("while randomizing principal %s"), pr_str); krb5_db_free_principal(util_context, &dbent, 1); exit_status++; return; } dbent.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; ret = krb5_timeofday(util_context, &now); if (ret) { com_err(me, ret, gettext("while getting time")); krb5_db_free_principal(util_context, &dbent, 1); exit_status++; return; } ret = krb5_dbe_update_last_pwd_change(util_context, &dbent, now); if (ret) { com_err(me, ret, gettext("while setting changetime")); krb5_db_free_principal(util_context, &dbent, 1); exit_status++; return; } ret = krb5_db_put_principal(util_context, &dbent, &n); krb5_db_free_principal(util_context, &dbent, 1); if (ret) { com_err(me, ret, gettext("while saving principal %s"), pr_str); exit_status++; return; } printf("%s changed\n", pr_str); } /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _KDB5_UTIL_H #define _KDB5_UTIL_H /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ #ifdef __cplusplus extern "C" { #endif /* * admin/edit/kdb5_edit.h * * Copyright 1992 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 #define MAX_HEADER 1024 #define REALM_SEP '@' #define REALM_SEP_STR "@" extern char *progname; extern char *Err_no_database; #ifndef V4_DECLARES_STATIC extern krb5_keyblock master_keyblock; extern krb5_principal master_princ; #endif extern krb5_boolean dbactive; extern int exit_status; extern krb5_context util_context; extern kadm5_config_params global_params; extern int valid_master_key; extern krb5_db_entry master_db; extern char **db5util_db_args; extern int db5util_db_args_size; extern int add_db_arg(char *arg); extern void usage(void); extern void add_key (char const *, char const *, krb5_const_principal, const krb5_keyblock *, krb5_kvno, krb5_keysalt *); extern int set_dbname_help (char *, char *); extern char *kdb5_util_Init (int, char **); extern int quit (void); extern int check_for_match (char *, int, krb5_db_entry *, int, int); extern void parse_token (char *, int *, int *, char *); extern int create_db_entry (krb5_principal, krb5_db_entry *); extern int kadm5_create_magic_princs (kadm5_config_params *params, krb5_context context); extern int process_ov_principal (char *fname, krb5_context kcontext, FILE *filep, int verbose, int *linenop); extern void load_db (int argc, char **argv); extern void dump_db (int argc, char **argv); extern void kdb5_create (int argc, char **argv); extern void kdb5_destroy (int argc, char **argv); extern void kdb5_stash (int argc, char **argv); extern void update_ok_file (char *file_name); extern int kadm5_create (kadm5_config_params *params); void usage (void); #ifdef __cplusplus } #endif #endif /* !_KDB5_UTIL_H */ /* Prototype for nstrtok */ char *nstrtok(char *, const char *delim); /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ #include #include #include #include "autoconf.h" #ifdef HAVE_MEMORY_H #include #endif #include #include #include #include #include "import_err.h" #include "kdb5_util.h" #include "nstrtok.h" #define LINESIZE 32768 /* XXX */ #define PLURAL(count) (((count) == 1) ? error_message(IMPORT_SINGLE_RECORD) : error_message(IMPORT_PLURAL_RECORDS)) static int parse_pw_hist_ent(current, hist) char *current; osa_pw_hist_ent *hist; { int tmp, i, j, ret; char *cp; ret = 0; hist->n_key_data = 1; hist->key_data = (krb5_key_data *) malloc(hist->n_key_data * sizeof(krb5_key_data)); if (hist->key_data == NULL) return ENOMEM; memset(hist->key_data, 0, sizeof(krb5_key_data)*hist->n_key_data); for (i = 0; i < hist->n_key_data; i++) { krb5_key_data *key_data = &hist->key_data[i]; key_data->key_data_ver = 1; if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } key_data->key_data_type[0] = atoi(cp); if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } key_data->key_data_length[0] = atoi(cp); if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } if(!(key_data->key_data_contents[0] = (krb5_octet *) malloc(key_data->key_data_length[0]+1))) { ret = ENOMEM; goto done; } for(j = 0; j < key_data->key_data_length[0]; j++) { if(sscanf(cp, "%02x", &tmp) != 1) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } key_data->key_data_contents[0][j] = tmp; cp = strchr(cp, ' ') + 1; } } done: return ret; } /* * Function: parse_principal * * Purpose: parse principal line in db dump file * * Arguments: * 0 on success, error code on failure * * Requires: * principal database to be opened. * nstrtok(3) to have a valid buffer in memory. * * Effects: * [effects] * * Modifies: * [modifies] * */ int process_ov_principal(fname, kcontext, filep, verbose, linenop) char *fname; krb5_context kcontext; FILE *filep; int verbose; int *linenop; { XDR xdrs; osa_princ_ent_t rec; krb5_error_code ret; krb5_tl_data tl_data; krb5_principal princ; krb5_db_entry kdb; char *current; char *cp; int x, one; krb5_boolean more; char line[LINESIZE]; if (fgets(line, LINESIZE, filep) == (char *) NULL) { return IMPORT_BAD_FILE; } if((cp = nstrtok(line, "\t")) == NULL) return IMPORT_BAD_FILE; if((rec = (osa_princ_ent_t) malloc(sizeof(osa_princ_ent_rec))) == NULL) return ENOMEM; memset(rec, 0, sizeof(osa_princ_ent_rec)); if((ret = krb5_parse_name(kcontext, cp, &princ))) goto done; krb5_unparse_name(kcontext, princ, ¤t); if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } else { if(strcmp(cp, "")) { if((rec->policy = (char *) malloc(strlen(cp)+1)) == NULL) { ret = ENOMEM; goto done; } strcpy(rec->policy, cp); } else rec->policy = NULL; } if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } rec->aux_attributes = strtol(cp, (char **)NULL, 16); if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } rec->old_key_len = atoi(cp); if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } rec->old_key_next = atoi(cp); if((cp = nstrtok((char *) NULL, "\t")) == NULL) { com_err(NULL, IMPORT_BAD_RECORD, "%s", current); ret = IMPORT_FAILED; goto done; } rec->admin_history_kvno = atoi(cp); if (! rec->old_key_len) { rec->old_keys = NULL; } else { if(!(rec->old_keys = (osa_pw_hist_ent *) malloc(sizeof(osa_pw_hist_ent) * rec->old_key_len))) { ret = ENOMEM; goto done; } memset(rec->old_keys,0, sizeof(osa_pw_hist_ent) * rec->old_key_len); for(x = 0; x < rec->old_key_len; x++) parse_pw_hist_ent(current, &rec->old_keys[x]); } xdralloc_create(&xdrs, XDR_ENCODE); if (! xdr_osa_princ_ent_rec(&xdrs, rec)) { xdr_destroy(&xdrs); ret = KADM5_XDR_FAILURE; goto done; } tl_data.tl_data_type = KRB5_TL_KADM_DATA; tl_data.tl_data_length = xdr_getpos(&xdrs); tl_data.tl_data_contents = (krb5_octet *) xdralloc_getdata(&xdrs); one = 1; ret = krb5_db_get_principal(kcontext, princ, &kdb, &one, &more); if (ret) goto done; ret = krb5_dbe_update_tl_data(kcontext, &kdb, &tl_data); if (ret) goto done; ret = krb5_db_put_principal(kcontext, &kdb, &one); if (ret) goto done; xdr_destroy(&xdrs); (*linenop)++; done: free(current); krb5_free_principal(kcontext, princ); osa_free_princ_ent(rec); return ret; } /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. * */ /* String table of messages for kadm5_create */ /* * I18n HACK. We define gettext(s) to be s so that we can extract the * strings here to the .po file. At the end of this file we will undef * gettext. */ #define gettext(s) s char *str_PARSE_NAME = gettext("while parsing admin principal name."); char *str_HISTORY_PARSE_NAME = gettext("while parsing admin history principal name."); char *str_ADMIN_PRINC_EXISTS = gettext("Warning! Admin principal already exists."); char *str_CHANGEPW_PRINC_EXISTS = gettext("Warning! Changepw principal already exists."); char *str_HISTORY_PRINC_EXISTS = gettext("Warning! Admin history principal already exists."); char *str_ADMIN_PRINC_WRONG_ATTRS = gettext("Warning! Admin principal has incorrect attributes.\n" "\tDISALLOW_TGT should be set, and max_life should be three hours.\n" "\tThis program will leave them as-is, but beware!."); char *str_CHANGEPW_PRINC_WRONG_ATTRS = gettext("Warning! Changepw principal has incorrect attributes.\n" "\tDISALLOW_TGT and PW_CHANGE_SERVICE should both be set, and " "max_life should be five minutes.\n" "\tThis program will leave them as-is, but beware!."); char *str_HISTORY_PRINC_WRONG_ATTRS = gettext("Warning! Admin history principal has incorrect attributes.\n" "\tDISALLOW_ALL_TIX should be set.\n" "\tThis program will leave it as-is, but beware!."); char *str_CREATED_PRINC_DB = gettext("%s: Admin principal database created " "(or it already existed).\n"); /* whoami */ char *str_CREATED_POLICY_DB = gettext("%s: Admin policy database created " "(or it already existed).\n"); /* whoami */ char *str_RANDOM_KEY = gettext("while calling random key for %s."); /* principal name */ char *str_ENCRYPT_KEY = gettext("while calling encrypt key for %s."); /* principal name */ char *str_PUT_PRINC = gettext("while storing %s in Kerberos database."); /* principal name */ char *str_CREATING_POLICY_DB = gettext("while creating/opening admin policy database."); char *str_CLOSING_POLICY_DB = gettext("while closing admin policy database."); char *str_CREATING_PRINC_DB = gettext("while creating/opening admin principal database."); char *str_CLOSING_PRINC_DB = gettext("while closing admin principal database."); char *str_CREATING_PRINC_ENTRY = gettext("while creating admin principal " "database entry for %s."); /* princ_name */ char *str_A_PRINC = gettext("a principal"); char *str_UNPARSE_PRINC = gettext("while unparsing principal."); char *str_CREATED_PRINC = gettext("%s: Created %s principal.\n"); /* whoami, princ_name */ char *str_INIT_KDB = gettext("while initializing kdb."); char *str_NO_KDB = gettext("while initializing kdb.\nThe Kerberos KDC database " "needs to exist in /krb5.\nIf you haven't run " "kdb5_create you need to do so before running this command."); char *str_INIT_RANDOM_KEY = gettext("while initializing random key generator."); char *str_TOO_MANY_ADMIN_PRINC = gettext("while fetching admin princ. Can only have one admin principal."); char *str_TOO_MANY_CHANGEPW_PRINC = gettext("while fetching changepw princ. " "Can only have one changepw principal."); char *str_TOO_MANY_HIST_PRINC = gettext("while fetching history princ. " "Can only have one history principal."); char *str_WHILE_DESTROYING_ADMIN_SESSION = gettext("while closing session with admin server and destroying tickets."); #undef gettext /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _STRING_TABLE_H #define _STRING_TABLE_H /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ #ifdef __cplusplus extern "C" { #endif /* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. * * $Header: /afs/athena.mit.edu/astaff/project/krbdev/.cvsroot/src/kadmin/\ * dbutil/string_table.h,v 1.2 1996/07/22 20:25:25 marc Exp $ * */ #ifndef _OVSEC_ADM_STRINGS_ extern char *str_PARSE_NAME; extern char *str_HISTORY_PARSE_NAME; extern char *str_ADMIN_PRINC_EXISTS; extern char *str_CHANGEPW_PRINC_EXISTS; extern char *str_HISTORY_PRINC_EXISTS; extern char *str_ADMIN_PRINC_WRONG_ATTRS; extern char *str_CHANGEPW_PRINC_WRONG_ATTRS; extern char *str_HISTORY_PRINC_WRONG_ATTRS; extern char *str_CREATED_PRINC_DB; extern char *str_CREATED_POLICY_DB; extern char *str_RANDOM_KEY; extern char *str_ENCRYPT_KEY; extern char *str_PUT_PRINC; extern char *str_CREATING_POLICY_DB; extern char *str_CLOSING_POLICY_DB; extern char *str_CREATING_PRINC_DB; extern char *str_CLOSING_PRINC_DB; extern char *str_CREATING_PRINC_ENTRY; extern char *str_A_PRINC; extern char *str_UNPARSE_PRINC; extern char *str_CREATED_PRINC; extern char *str_INIT_KDB; extern char *str_NO_KDB; extern char *str_INIT_RANDOM_KEY; extern char *str_TOO_MANY_ADMIN_PRINC; extern char *str_TOO_MANY_CHANGEPW_PRINC; extern char *str_TOO_MANY_HIST_PRINC; extern char *str_WHILE_DESTROYING_ADMIN_SESSION; #endif /* _OVSEC_ADM_STRINGS_ */ #ifdef __cplusplus } #endif #endif /* !_STRING_TABLE_H */ /* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved * */ /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include "nstrtok.h" /* * Function: nstrtok * * Purpose: the same as strtok ... just different. does not deal with * multiple tokens in row. * * Arguments: * s (input) string to scan * delim (input) list of delimiters * string or null on error. * * Requires: * nuttin * * Effects: * sets last to string * * Modifies: * last * */ char * nstrtok(s, delim) register char *s; register const char *delim; { register const char *spanp; register int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) return (NULL); /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). */ #ifdef OLD cont: c = *s++; for (spanp = delim; (sc = *spanp++) != 0;) { if (c == sc) goto cont; } if (c == 0) { /* no non-delimiter characters */ last = NULL; return (NULL); } tok = s - 1; #else tok = s; #endif /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL; we stop if we see that, too. */ for (;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Openvision retains the copyright to derivative works of * this source code. Do *NOT* create a derivative of this * source code before consulting with your legal department. * Do *NOT* integrate *ANY* of this source code into another * product before consulting with your legal department. * * For further information, read the top-level Openvision * copyright which is contained in the top-level MIT Kerberos * copyright. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * */ /* * admin/edit/util.c * * Copyright 1992 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. * * Utilities for kdb5_edit. * * Some routines derived from code contributed by the Sandia National * Laboratories. Sandia National Laboratories also makes no * representations about the suitability of the modifications, or * additions to this software for any purpose. It is provided "as is" * without express or implied warranty. * */ #include #include "./kdb5_edit.h" #ifndef HAVE_STRSTR char * strstr(s1, s2) char *s1; char *s2; { int s2len; int i; char *temp_ptr; temp_ptr = s1; for ( i = 0; i < strlen(s1); i++) { if (memcmp(temp_ptr, s2, strlen(s2)) == 0) return(temp_ptr); temp_ptr += 1; } return ((char *) 0); } #endif /* HAVE_STRSTR */ void parse_token(token_in, must_be_first_char, num_tokens, tokens_out) char *token_in; int *must_be_first_char; int *num_tokens; char *tokens_out; { int i, j; int token_count = 0; i = 0; j = 0; /* Eliminate Up Front Asterisks */ *must_be_first_char = 1; for (i = 0; token_in[i] == '*'; i++) { *must_be_first_char = 0; } if (i == strlen(token_in)) { *num_tokens = 0; return; } /* Fill first token_out */ token_count++; while ((token_in[i] != '*') && (token_in[i] != '\0')) { tokens_out[j] = token_in[i]; j++; i++; } if (i == strlen(token_in)) { tokens_out[j] = '\0'; *num_tokens = token_count; return; } /* Then All Subsequent Tokens */ while (i < strlen(token_in)) { if (token_in[i] == '*') { token_count++; tokens_out[j] = '\t'; } else { tokens_out[j] = token_in[i]; } i++; j++; } tokens_out[j] = '\0'; if (tokens_out[j - 1] == '\t') { token_count--; tokens_out[j - 1] = '\0'; } *num_tokens = token_count; return; } int check_for_match(search_field, must_be_first_character, chk_entry, num_tokens, type) int must_be_first_character; char *search_field; krb5_db_entry *chk_entry; int num_tokens; int type; { char token1[256]; char *found1; char token2[256]; char *found2; char token3[256]; char *found3; char *local_entry; local_entry = chk_entry->princ->data[type].data; token1[0] = token2[0] = token3[0] = '\0'; (void) sscanf(search_field, "%s\t%s\t%s", token1, token2, token3); found1 = strstr(local_entry, token1); if (must_be_first_character && (found1 != local_entry)) return(0); if (found1 && (num_tokens == 1)) return(1); if (found1 && (num_tokens > 1)) { found2 = strstr(local_entry, token2); if (found2 && (found2 > found1) && (num_tokens == 2)) return(1); } if ((found2 > found1) && (num_tokens == 3)) { found3 = strstr(local_entry, token3); if (found3 && (found3 > found2) && (found2 > found1)) return(1); } return(0); }