1 /* 2 | * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 2 | * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 | #pragma ident "@(#)dump.c 1.9 04/09/08 SMI" 6 | #pragma ident "@(#)dump.c 1.8 04/05/04 SMI" 7 8 /* 9 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 10 * 11 * Openvision retains the copyright to derivative works of 12 * this source code. Do *NOT* create a derivative of this 13 * source code before consulting with your legal department. 14 * Do *NOT* integrate *ANY* of this source code into another 15 * product before consulting with your legal department. 16 * 17 * For further information, read the top-level Openvision 18 * copyright which is contained in the top-level MIT Kerberos 19 * copyright. 20 * 21 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 22 * 23 */ 24 25 26 /* 27 * admin/edit/dump.c 28 * 29 * Copyright 1990,1991 by the Massachusetts Institute of Technology. 30 * All Rights Reserved. 31 * 32 * Export of this software from the United States of America may 33 * require a specific license from the United States Government. 34 * It is the responsibility of any person or organization contemplating 35 * export to obtain such a license before exporting. 36 * 37 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 38 * distribute this software and its documentation for any purpose and 39 * without fee is hereby granted, provided that the above copyright 40 * notice appear in all copies and that both that copyright notice and 41 * this permission notice appear in supporting documentation, and that 42 * the name of M.I.T. not be used in advertising or publicity pertaining 43 * to distribution of the software without specific, written prior 44 * permission. Furthermore if you modify this software you must label 45 * your software as modified software and not distribute it in such a 46 * fashion that it might be confused with the original M.I.T. software. 47 * M.I.T. makes no representations about the suitability of 48 * this software for any purpose. It is provided "as is" without express 49 * or implied warranty. 50 * 51 * 52 * Dump a KDC database 53 */ 54 55 #define KDB5_DISPATCH 56 #define KRB5_KDB5_DBM__ 57 #include <k5-int.h> 58 /* #define these to avoid an indirection function; for future implementations, 59 these may be redirected from a dispatch table/routine */ 60 /* SUNWresync121 - this appears to be an orig SEAM thang */ 61 #define krb5_dbm_db_set_name krb5_db_set_name 62 #define krb5_dbm_db_set_nonblocking krb5_db_set_nonblocking 63 #define krb5_dbm_db_init krb5_db_init 64 #define krb5_dbm_db_get_age krb5_db_get_age 65 #define krb5_dbm_db_create krb5_db_create 66 #define krb5_dbm_db_rename krb5_db_rename 67 #define krb5_dbm_db_get_principal krb5_db_get_principal 68 #define krb5_dbm_db_free_principal krb5_db_free_principal 69 #define krb5_dbm_db_put_principal krb5_db_put_principal 70 #define krb5_dbm_db_delete_principal krb5_db_delete_principal 71 #define krb5_dbm_db_lock krb5_db_lock 72 #define krb5_dbm_db_unlock krb5_db_unlock 73 #define krb5_dbm_db_set_lockmode krb5_db_set_lockmode 74 #define krb5_dbm_db_close_database krb5_db_close_database 75 #define krb5_dbm_db_open_database krb5_db_open_database 76 #define krb5_dbm_db_iterate krb5_db_iterate 77 78 #include <stdio.h> 79 #include <com_err.h> 80 #include <kadm5/admin.h> 81 #include <kadm5/adb.h> 82 #include <libintl.h> 83 84 #include "kdb5_util.h" 85 86 #if HAVE_REGEX_H 87 #include <regex.h> 88 #endif /* HAVE_REGEX_H */ 89 90 /* 91 * Needed for master key conversion. 92 */ 93 extern krb5_keyblock master_key; 94 extern krb5_principal master_princ; 95 extern int valid_master_key; 96 extern void usage(); 97 static int mkey_convert; 98 static krb5_keyblock new_master_key; 99 100 /* 101 * Use compile(3) if no regcomp present. 102 */ 103 #if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H) 104 #define INIT char *sp = instring; 105 #define GETC() (*sp++) 106 #define PEEKC() (*sp) 107 #define UNGETC(c) (--sp) 108 #define RETURN(c) return(c) 109 #define ERROR(c) 110 #define RE_BUF_SIZE 1024 111 #include <regexp.h> 112 #endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */ 113 114 struct dump_args { 115 char *programname; 116 FILE *ofile; 117 krb5_context kcontext; 118 char **names; 119 int nnames; 120 int verbose; 121 }; 122 123 static krb5_error_code dump_k5beta_iterator 124 PROTOTYPE((krb5_pointer, 125 krb5_db_entry *)); 126 static krb5_error_code dump_k5beta6_iterator 127 PROTOTYPE((krb5_pointer, 128 krb5_db_entry *)); 129 + static krb5_error_code dump_iprop_iterator 130 + PROTOTYPE((krb5_pointer, 131 + krb5_db_entry *)); 132 static krb5_error_code dump_k5beta7_princ 133 PROTOTYPE((krb5_pointer, 134 krb5_db_entry *)); 135 + static krb5_error_code dump_iprop_princ 136 + PROTOTYPE((krb5_pointer, 137 + krb5_db_entry *)); 138 static krb5_error_code dump_ov_princ 139 PROTOTYPE((krb5_pointer, 140 krb5_db_entry *)); 141 static void dump_k5beta7_policy PROTOTYPE((void *, osa_policy_ent_t)); 142 143 typedef 144 krb5_error_code(*dump_func) PROTOTYPE((krb5_pointer, 145 krb5_db_entry *)); 146 147 static int process_k5beta_record 148 PROTOTYPE((char *, krb5_context, 149 FILE *, int, int *, void *)); 150 static int process_k5beta6_record 151 PROTOTYPE((char *, krb5_context, 152 FILE *, int, int *, void *)); 153 static int process_k5beta7_record 154 PROTOTYPE((char *, krb5_context, 155 FILE *, int, int *, void *)); 156 static int process_ov_record 157 PROTOTYPE((char *, krb5_context, 158 FILE *, int, int *, void *)); 159 typedef 160 krb5_error_code(*load_func) PROTOTYPE((char *, krb5_context, 161 FILE *, int, int *, void *)); 162 163 typedef struct _dump_version { 164 char *name; 165 char *header; 166 int updateonly; 167 int create_kadm5; 168 dump_func dump_princ; 169 osa_adb_iter_policy_func dump_policy; 170 load_func load_record; 171 } dump_version; 200 + dump_version iprop_version = { 201 + "Kerberos iprop version", 202 + "iprop", 203 + 0, 204 + 0, 205 + dump_iprop_princ, 206 + dump_k5beta7_policy, 207 + process_k5beta7_record, 208 + }; 209 dump_version ov_version = { 210 "OpenV*Secure V1.0", 211 "OpenV*Secure V1.0\t", 212 1, 213 1, 214 dump_ov_princ, 215 dump_k5beta7_policy, 216 process_ov_record, 217 }; 218 219 /* External data */ 220 extern char *current_dbname; 221 extern krb5_boolean dbactive; 222 extern int exit_status; 223 extern krb5_context util_context; 224 extern kadm5_config_params global_params; 225 226 /* Strings */ 227 228 static const char k5beta_dump_header[] = "kdb5_edit load_dump version 2.0\n"; 229 static const char k5beta6_dump_header[] = "kdb5_edit load_dump version 3.0\n"; 230 static const char k5beta7_dump_header[] = "kdb5_edit load_dump version 4\n"; 231 232 static const char null_mprinc_name[] = "kdb5_dump@MISSING"; 233 234 /* 235 * We define gettext(s) to be s here, so that xgettext will extract the 236 * strings to the .po file. At the end of the message section we will 237 * undef gettext so that we can use it as a funtion. 238 */ 239 240 #define gettext(s) s 241 242 /* Message strings */ 243 static const char regex_err[] = 244 gettext("%s: regular expression error - %s\n"); 245 static const char regex_merr[] = 246 gettext("%s: regular expression match error - %s\n"); 247 static const char pname_unp_err[] = 248 gettext("%s: cannot unparse principal name (%s)\n"); 249 static const char mname_unp_err[] = 250 gettext("%s: cannot unparse modifier name (%s)\n"); 251 static const char nokeys_err[] = 252 gettext("%s: cannot find any standard key for %s\n"); 253 static const char sdump_tl_inc_err[] = 254 gettext("%s: tagged data list inconsistency for %s " 255 "(counted %d, stored %d)\n"); 256 static const char stand_fmt_name[] = 257 gettext("Kerberos version 5"); 258 static const char old_fmt_name[] = 259 gettext("Kerberos version 5 old format"); 260 static const char b6_fmt_name[] = 261 gettext("Kerberos version 5 beta 6 format"); 262 static const char ofopen_error[] = 263 gettext("%s: cannot open %s for writing (%s)\n"); 264 static const char oflock_error[] = 265 gettext("%s: cannot lock %s (%s)\n"); 266 static const char dumprec_err[] = 267 gettext("%s: error performing %s dump (%s)\n"); 268 static const char dumphdr_err[] = 269 gettext("%s: error dumping %s header (%s)\n"); 270 static const char trash_end_fmt[] = 271 gettext("%s(%d): ignoring trash at end of line: "); 272 static const char read_name_string[] = 273 gettext("name string"); 274 static const char read_key_type[] = 275 gettext("key type"); 276 static const char read_key_data[] = 277 gettext("key data"); 278 static const char read_pr_data1[] = 279 gettext("first set of principal attributes"); 280 static const char read_mod_name[] = 281 gettext("modifier name"); 282 static const char read_pr_data2[] = 283 gettext("second set of principal attributes"); 284 static const char read_salt_data[] = 285 gettext("salt data"); 286 static const char read_akey_type[] = 287 gettext("alternate key type"); 288 static const char read_akey_data[] = 289 gettext("alternate key data"); 290 static const char read_asalt_type[] = 291 gettext("alternate salt type"); 292 static const char read_asalt_data[] = 293 gettext("alternate salt data"); 294 static const char read_exp_data[] = 295 gettext("expansion data"); 296 static const char store_err_fmt[] = 297 gettext("%s(%d): cannot store %s(%s)\n"); 298 static const char add_princ_fmt[] = 299 gettext("%s\n"); 300 static const char parse_err_fmt[] = 301 gettext("%s(%d): cannot parse %s (%s)\n"); 302 static const char read_err_fmt[] = 303 gettext("%s(%d): cannot read %s\n"); 304 static const char no_mem_fmt[] = 305 gettext("%s(%d): no memory for buffers\n"); 306 static const char rhead_err_fmt[] = 307 gettext("%s(%d): cannot match size tokens\n"); 308 static const char err_line_fmt[] = 309 gettext("%s: error processing line %d of %s\n"); 310 static const char head_bad_fmt[] = 311 gettext("%s: dump header bad in %s\n"); 312 static const char read_bytecnt[] = 313 gettext("record byte count"); 314 static const char read_encdata[] = 315 gettext("encoded data"); 316 static const char n_name_unp_fmt[] = 317 gettext("%s(%s): cannot unparse name\n"); 318 static const char n_dec_cont_fmt[] = 319 gettext("%s(%s): cannot decode contents\n"); 320 static const char read_nint_data[] = 321 gettext("principal static attributes"); 322 static const char read_tcontents[] = 323 gettext("tagged data contents"); 324 static const char read_ttypelen[] = 325 gettext("tagged data type and length"); 326 static const char read_kcontents[] = 327 gettext("key data contents"); 328 static const char read_ktypelen[] = 329 gettext("key data type and length"); 330 static const char read_econtents[] = 331 gettext("extra data contents"); 332 static const char k5beta_fmt_name[] = 333 gettext("Kerberos version 5 old format"); 334 static const char standard_fmt_name[] = 335 gettext("Kerberos version 5 format"); 336 static const char no_name_mem_fmt[] = 337 gettext("%s: cannot get memory for temporary name\n"); 338 static const char ctx_err_fmt[] = 339 gettext("%s: cannot initialize Kerberos context\n"); 340 static const char stdin_name[] = 341 gettext("standard input"); 342 static const char remaster_err_fmt[] = 343 gettext("while re-encoding keys for principal %s with new master key"); 344 static const char restfail_fmt[] = 345 gettext("%s: %s restore failed\n"); 346 static const char close_err_fmt[] = 347 gettext("%s: cannot close database (%s)\n"); 348 static const char dbinit_err_fmt[] = 349 gettext("%s: cannot initialize database (%s)\n"); 350 static const char dblock_err_fmt[] = 351 gettext("%s: cannot initialize database lock (%s)\n"); 352 static const char dbname_err_fmt[] = 353 gettext("%s: cannot set database name to %s (%s)\n"); 354 static const char dbdelerr_fmt[] = 355 gettext("%s: cannot delete bad database %s (%s)\n"); 356 static const char dbunlockerr_fmt[] = 357 gettext("%s: cannot unlock database %s (%s)\n"); 358 static const char dbrenerr_fmt[] = 359 gettext("%s: cannot rename database %s to %s (%s)\n"); 360 static const char dbcreaterr_fmt[] = 361 gettext("%s: cannot create database %s (%s)\n"); 362 static const char dfile_err_fmt[] = 363 gettext("%s: cannot open %s (%s)\n"); 364 365 /* 366 * We now return you to your regularly scheduled program. 367 */ 368 #undef gettext 369 370 static const char oldoption[] = "-old"; 371 static const char b6option[] = "-b6"; 372 + static const char ipropoption[] = "-i"; 373 static const char verboseoption[] = "-verbose"; 374 static const char updateoption[] = "-update"; 375 static const char hashoption[] = "-hash"; 376 static const char ovoption[] = "-ov"; 377 static const char dump_tmptrail[] = "~"; 378 379 /* 380 * Re-encrypt the key_data with the new master key... 381 */ 382 krb5_error_code master_key_convert(context, db_entry) 383 krb5_context context; 384 krb5_db_entry * db_entry; 385 { 386 krb5_error_code retval; 387 krb5_keyblock v5plainkey, *key_ptr; 388 krb5_keysalt keysalt; 389 int i; 390 krb5_key_data new_key_data, *key_data; 391 krb5_boolean is_mkey; 392 393 is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ); 394 395 if (is_mkey && db_entry->n_key_data != 1) 396 fprintf(stderr, 397 gettext( 398 "Master key db entry has %d keys, expecting only 1!\n"), 399 db_entry->n_key_data); 400 for (i=0; i < db_entry->n_key_data; i++) { 401 key_data = &db_entry->key_data[i]; 402 if (key_data->key_data_length == 0) 403 continue; 404 retval = krb5_dbekd_decrypt_key_data(context, &master_key, 405 key_data, &v5plainkey, 406 &keysalt); 407 if (retval) 408 return retval; 409 410 memset(&new_key_data, 0, sizeof(new_key_data)); 411 key_ptr = is_mkey ? &new_master_key : &v5plainkey; 412 retval = krb5_dbekd_encrypt_key_data(context, &new_master_key, 413 key_ptr, &keysalt, 414 key_data->key_data_kvno, 415 &new_key_data); 416 if (retval) 417 return retval; 418 krb5_free_keyblock_contents(context, &v5plainkey); 419 free(key_data->key_data_contents); 420 *key_data = new_key_data; 421 } 422 return 0; 423 } 974 + /* 975 + * dump_iprop_iterator() - Output a dump record in iprop format. 976 + */ 977 + static krb5_error_code 978 + dump_iprop_iterator(ptr, entry) 979 + krb5_pointer ptr; 980 + krb5_db_entry *entry; 981 + { 982 + krb5_error_code retval; 983 + struct dump_args *arg; 984 + char *name; 985 + krb5_tl_data *tlp; 986 + krb5_key_data *kdata; 987 + int counter, i, j; 988 989 + /* Initialize */ 990 + arg = (struct dump_args *) ptr; 991 + name = (char *) NULL; 992 + 993 /* 994 + * Flatten the principal name. 995 + */ 996 + if ((retval = krb5_unparse_name(arg->kcontext, 997 + entry->princ, 998 + &name))) { 999 + fprintf(stderr, gettext(pname_unp_err), 1000 + arg->programname, error_message(retval)); 1001 + return(retval); 1002 + } 1003 + 1004 + /* 1005 + * Re-encode the keys in the new master key, if necessary. 1006 + */ 1007 + if (mkey_convert) { 1008 + retval = master_key_convert(arg->kcontext, entry); 1009 + if (retval) { 1010 + com_err(arg->programname, retval, remaster_err_fmt, name); 1011 + return retval; 1012 + } 1013 + } 1014 + 1015 + /* 1016 + * If we don't have any match strings, or if our name matches, then 1017 + * proceed with the dump, otherwise, just forget about it. 1018 + */ 1019 + if (!arg->nnames || name_matches(name, arg)) { 1020 + /* 1021 + * We'd like to just blast out the contents as they would 1022 + * appear in the database so that we can just suck it back 1023 + * in, but it doesn't lend itself to easy editing. 1024 + */ 1025 + 1026 + /* 1027 + * The dump format is as follows: len strlen(name) 1028 + * n_tl_data n_key_data e_length name attributes max_life 1029 + * max_renewable_life expiration pw_expiration last_success 1030 + * last_failed fail_auth_count n_tl_data*[type length 1031 + * <contents>] n_key_data*[ver kvno ver*(type length 1032 + * <contents>)] <e_data> Fields which are not encapsulated 1033 + * by angle-brackets are to appear verbatim. Bracketed 1034 + * fields absence is indicated by a -1 in its place 1035 + */ 1036 + 1037 + /* 1038 + * Make sure that the tagged list is reasonably correct. 1039 + */ 1040 + counter = 0; 1041 + for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) 1042 + counter++; 1043 + 1044 + if (counter == entry->n_tl_data) { 1045 + /* Pound out header */ 1046 + fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%s\t", 1047 + (int) entry->len, 1048 + strlen(name), 1049 + (int) entry->n_tl_data, 1050 + (int) entry->n_key_data, 1051 + (int) entry->e_length, 1052 + name); 1053 + fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", 1054 + entry->attributes, 1055 + entry->max_life, 1056 + entry->max_renewable_life, 1057 + entry->expiration, 1058 + entry->pw_expiration, 1059 + entry->last_success, 1060 + entry->last_failed, 1061 + entry->fail_auth_count); 1062 + /* Pound out tagged data. */ 1063 + for (tlp = entry->tl_data; tlp; 1064 + tlp = tlp->tl_data_next) { 1065 + fprintf(arg->ofile, "%d\t%d\t", 1066 + (int) tlp->tl_data_type, 1067 + (int) tlp->tl_data_length); 1068 + if (tlp->tl_data_length) 1069 + for (i = 0; 1070 + i < tlp->tl_data_length; 1071 + i++) 1072 + fprintf(arg->ofile, "%02x", 1073 + tlp-> 1074 + tl_data_contents[i]); 1075 + else 1076 + fprintf(arg->ofile, "%d", -1); 1077 + fprintf(arg->ofile, "\t"); 1078 + } 1079 + 1080 + /* Pound out key data */ 1081 + for (counter = 0; 1082 + counter < entry->n_key_data; counter++) { 1083 + kdata = &entry->key_data[counter]; 1084 + fprintf(arg->ofile, "%d\t%d\t", 1085 + (int) kdata->key_data_ver, 1086 + (int) kdata->key_data_kvno); 1087 + for (i=0; i<kdata->key_data_ver; i++) { 1088 + fprintf(arg->ofile, "%d\t%d\t", 1089 + kdata->key_data_type[i], 1090 + kdata->key_data_length[i]); 1091 + if (kdata->key_data_length[i]) 1092 + for (j = 0; 1093 + j < kdata-> 1094 + key_data_length[i]; 1095 + j++) 1096 + fprintf(arg->ofile, 1097 + "%02x", 1098 + kdata-> 1099 + key_data_contents 1100 + [i][j]); 1101 + else 1102 + fprintf(arg->ofile, "%d", -1); 1103 + fprintf(arg->ofile, "\t"); 1104 + } 1105 + } 1106 + 1107 + /* Pound out extra data */ 1108 + if (entry->e_length) 1109 + for (i=0; i<entry->e_length; i++) 1110 + fprintf(arg->ofile, "%02x", 1111 + entry->e_data[i]); 1112 + else 1113 + fprintf(arg->ofile, "%d", -1); 1114 + 1115 + /* Print trailer */ 1116 + fprintf(arg->ofile, ";\n"); 1117 + 1118 + if (arg->verbose) 1119 + fprintf(stderr, "%s\n", name); 1120 + } else { 1121 + fprintf(stderr, gettext(sdump_tl_inc_err), 1122 + arg->programname, name, counter, 1123 + (int) entry->n_tl_data); 1124 + retval = EINVAL; 1125 + } 1126 + } 1127 + krb5_xfree(name); 1128 + return(retval); 1129 + } 1130 + 1131 + /* 1132 * dump_k5beta7_iterator() - Output a dump record in krb5b7 format. 1133 */ 1134 static krb5_error_code 1135 dump_k5beta7_princ(ptr, entry) 1136 krb5_pointer ptr; 1137 krb5_db_entry *entry; 1138 { 1139 krb5_error_code retval; 1140 struct dump_args *arg; 1141 char *name; 1142 int tmp_nnames; 1143 1144 /* Initialize */ 1145 arg = (struct dump_args *) ptr; 1146 name = (char *) NULL; 1147 1148 /* 1149 * Flatten the principal name. 1150 */ 1151 if ((retval = krb5_unparse_name(arg->kcontext, 1152 entry->princ, 1153 &name))) { 1154 fprintf(stderr, gettext(pname_unp_err), 1155 arg->programname, error_message(retval)); 1156 return(retval); 1157 } 1158 /* 1159 * If we don't have any match strings, or if our name matches, then 1160 * proceed with the dump, otherwise, just forget about it. 1161 */ 1162 if (!arg->nnames || name_matches(name, arg)) { 1163 fprintf(arg->ofile, "princ\t"); 1164 1165 /* save the callee from matching the name again */ 1166 tmp_nnames = arg->nnames; 1167 arg->nnames = 0; 1168 retval = dump_k5beta6_iterator(ptr, entry); 1169 arg->nnames = tmp_nnames; 1170 } 1171 free(name); 1172 return (retval); 1173 } 1174 1175 + /* 1176 + * dump_iprop_princ() - Output a dump record in iprop format. 1177 + * This was created in order to dump more data, such as kadm5 tl 1178 + */ 1179 + static krb5_error_code 1180 + dump_iprop_princ(ptr, entry) 1181 + krb5_pointer ptr; 1182 + krb5_db_entry *entry; 1183 + { 1184 + krb5_error_code retval; 1185 + struct dump_args *arg; 1186 + char *name; 1187 + int tmp_nnames; 1188 + 1189 + /* Initialize */ 1190 + arg = (struct dump_args *) ptr; 1191 + name = (char *) NULL; 1192 + 1193 + /* 1194 + * Flatten the principal name. 1195 + */ 1196 + if ((retval = krb5_unparse_name(arg->kcontext, 1197 + entry->princ, 1198 + &name))) { 1199 + fprintf(stderr, gettext(pname_unp_err), 1200 + arg->programname, error_message(retval)); 1201 + return(retval); 1202 + } 1203 + /* 1204 + * If we don't have any match strings, or if our name matches, then 1205 + * proceed with the dump, otherwise, just forget about it. 1206 + */ 1207 + if (!arg->nnames || name_matches(name, arg)) { 1208 + fprintf(arg->ofile, "princ\t"); 1209 + 1210 + /* save the callee from matching the name again */ 1211 + tmp_nnames = arg->nnames; 1212 + arg->nnames = 0; 1213 + retval = dump_iprop_iterator(ptr, entry); 1214 + arg->nnames = tmp_nnames; 1215 + } 1216 + free(name); 1217 + return (retval); 1218 + } 1219 void 1220 dump_k5beta7_policy(void *data, osa_policy_ent_t entry) 1221 { 1222 struct dump_args *arg; 1223 1224 arg = (struct dump_args *) data; 1225 fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", entry->name, 1226 entry->pw_min_life, entry->pw_max_life, entry->pw_min_length, 1227 entry->pw_min_classes, entry->pw_history_num, 1228 entry->policy_refcnt); 1229 } ----Unchanged portion omitted---- 1342 1343 /* 1344 * usage is: 1345 * dump_db [-i] [-old] [-b6] [-ov] [-verbose] [filename [principals...]] 1346 */ 1347 void 1348 dump_db(argc, argv) 1349 int argc; 1350 char **argv; 1351 { 1352 FILE *f; 1353 struct dump_args arglist; 1354 int error; 1355 char *programname; 1356 char *ofile; 1357 krb5_error_code kret, retval; 1358 dump_version *dump; 1359 int aindex; 1360 krb5_boolean locked; 1361 extern osa_adb_policy_t policy_db; 1362 char *new_mkey_file = 0; 1363 + bool_t dump_sno = FALSE; 1364 + kdb_log_context *log_ctx; 1365 1366 /* 1367 * Parse the arguments. 1368 */ 1369 programname = argv[0]; 1370 if (strrchr(programname, (int) '/')) 1371 programname = strrchr(argv[0], (int) '/') + 1; 1372 ofile = (char *) NULL; 1373 error = 0; 1374 dump = &beta7_version; 1375 arglist.verbose = 0; 1376 new_mkey_file = 0; 1377 mkey_convert = 0; 1378 + log_ctx = util_context->kdblog_context; 1379 1380 /* 1381 * Parse the qualifiers. 1382 */ 1383 for (aindex = 1; aindex < argc; aindex++) { 1384 if (strcmp(argv[aindex], oldoption) == 0) 1385 dump = &old_version; 1386 else if (strcmp(argv[aindex], b6option) == 0) 1387 dump = &beta6_version; 1388 else if (strcmp(argv[aindex], ovoption) == 0) 1389 dump = &ov_version; 1390 + else if (!strcmp(argv[aindex], ipropoption)) { 1391 + if (log_ctx && log_ctx->iproprole) { 1392 + dump = &iprop_version; 1393 + /* 1394 + * dump_sno is used to indicate if the serial 1395 + * # should be populated in the output 1396 + * file to be used later by iprop for updating 1397 + * the slave's update log when loading 1398 + */ 1399 + dump_sno = TRUE; 1400 + } else { 1401 + fprintf(stderr, gettext("Iprop not enabled\n")); 1402 + exit_status++; 1403 + return; 1404 + } 1405 + } 1406 else if (strcmp(argv[aindex], verboseoption) == 0) 1407 arglist.verbose++; 1408 else if (!strcmp(argv[aindex], "-mkey_convert")) 1409 mkey_convert = 1; 1410 else if (!strcmp(argv[aindex], "-new_mkey_file")) { 1411 new_mkey_file = argv[++aindex]; 1412 mkey_convert = 1; 1413 } else 1414 break; 1415 } 1416 1417 arglist.names = (char **) NULL; 1418 arglist.nnames = 0; 1419 if (aindex < argc) { 1420 ofile = argv[aindex]; 1421 aindex++; 1422 if (aindex < argc) { 1423 arglist.names = &argv[aindex]; 1424 arglist.nnames = argc - aindex; 1425 } 1426 } 1427 1428 /* 1429 * Make sure the database is open. The policy database only has 1430 * to be opened if we try a dump that uses it. 1431 */ 1432 if (!dbactive || (dump->dump_policy != NULL && policy_db == NULL)) { 1433 com_err(argv[0], 0, Err_no_database); 1434 exit_status++; 1435 return; 1436 } 1437 1438 /* 1439 * If we're doing a master key conversion, set up for it. 1440 */ 1441 if (mkey_convert) { 1442 if (!valid_master_key) { 1443 /* TRUE here means read the keyboard, but only once */ 1444 retval = krb5_db_fetch_mkey(util_context, 1445 master_princ, 1446 global_params.enctype, 1447 TRUE, FALSE, 1448 (char *) NULL, 0, 1449 &master_key); 1450 if (retval) { 1451 com_err(argv[0], retval, 1452 gettext("while reading master key")); 1453 exit(1); 1454 } 1455 retval = krb5_db_verify_master_key(util_context, 1456 master_princ, 1457 &master_key); 1458 if (retval) { 1459 com_err(argv[0], retval, 1460 gettext("while verifying master key")); 1461 exit(1); 1462 } 1463 } 1464 if (!new_mkey_file) 1465 printf(gettext("Please enter new master key....\n")); 1466 1467 if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 1468 global_params.enctype, 1469 !new_mkey_file, TRUE, 1470 new_mkey_file, 0, 1471 &new_master_key))) { 1472 com_err(argv[0], retval, 1473 gettext("while reading new master key")); 1474 exit(1); 1475 } 1476 } 1477 1478 kret = 0; 1479 locked = 0; 1480 if (ofile && strcmp(ofile, "-")) { 1481 /* 1482 * Make sure that we don't open and truncate on the fopen, 1483 * since that may hose an on-going kprop process. 1484 * 1485 * We could also control this by opening for read and write, 1486 * doing an flock with LOCK_EX, and then truncating the 1487 * file once we have gotten the lock, but that would 1488 * involve more OS dependencies than I want to get into. 1489 */ 1490 unlink(ofile); 1491 if (!(f = fopen(ofile, "w"))) { 1492 fprintf(stderr, gettext(ofopen_error), 1493 programname, ofile, error_message(errno)); 1494 exit_status++; 1495 return; 1496 } 1497 if ((kret = krb5_lock_file(util_context, 1498 fileno(f), 1499 KRB5_LOCKMODE_EXCLUSIVE))) { 1500 fprintf(stderr, gettext(oflock_error), 1501 programname, ofile, error_message(kret)); 1502 exit_status++; 1503 } else 1504 locked = 1; 1505 } else { 1506 f = stdout; 1507 } 1508 if (f && !(kret)) { 1509 arglist.programname = programname; 1510 arglist.ofile = f; 1511 arglist.kcontext = util_context; 1512 fprintf(arglist.ofile, "%s", dump->header); 1513 1514 + if (dump_sno) { 1515 + if (ulog_map(util_context, &global_params, FKCOMMAND)) { 1516 + fprintf(stderr, 1517 + gettext("%s: Could not map log\n"), programname); 1518 + exit_status++; 1519 + goto error; 1520 + } 1521 + 1522 + /* 1523 + * We grab the lock twice (once again in the iterator call), 1524 + * but that's ok since the lock func handles incr locks held. 1525 + */ 1526 + if (krb5_db_lock(util_context, KRB5_LOCKMODE_SHARED)) { 1527 + fprintf(stderr, 1528 + gettext("%s: Couldn't grab lock\n"), programname); 1529 + exit_status++; 1530 + goto error; 1531 + } 1532 + 1533 + fprintf(f, " %u", log_ctx->ulog->kdb_last_sno); 1534 + fprintf(f, " %u", log_ctx->ulog->kdb_last_time.seconds); 1535 + fprintf(f, " %u", log_ctx->ulog->kdb_last_time.useconds); 1536 + } 1537 + 1538 if (dump->header[strlen(dump->header)-1] != '\n') 1539 fputc('\n', arglist.ofile); 1540 1541 if ((kret = krb5_dbm_db_iterate(util_context, 1542 dump->dump_princ, 1543 (krb5_pointer) &arglist))) { 1544 fprintf(stderr, gettext(dumprec_err), 1545 programname, dump->name, error_message(kret)); 1546 exit_status++; 1547 + if (dump_sno) 1548 + (void) krb5_db_unlock(util_context); 1549 } 1550 if (dump->dump_policy && 1551 (kret = osa_adb_iter_policy(policy_db, dump->dump_policy, 1552 &arglist))) { 1553 fprintf(stderr, gettext(dumprec_err), 1554 programname, dump->name, 1555 error_message(kret)); 1556 exit_status++; 1557 } 1558 1559 error: 1560 if (ofile && f != stdout && !exit_status) { 1561 fclose(f); 1562 update_ok_file(ofile); 1563 } 1564 } 1565 if (locked) 1566 (void) krb5_lock_file(util_context, 1567 fileno(f), KRB5_LOCKMODE_UNLOCK); 1568 } ----Unchanged portion omitted---- 2558 2559 /* 2560 * Usage: load_db [-i] [-old] [-ov] [-b6] [-verbose] [-update] [-hash] filename 2561 */ 2562 void 2563 load_db(argc, argv) 2564 int argc; 2565 char **argv; 2566 { 2567 kadm5_config_params newparams; 2568 osa_adb_policy_t tmppol_db; 2569 krb5_error_code kret; 2570 krb5_context kcontext; 2571 FILE *f; 2572 extern char *optarg; 2573 extern int optind; 2574 char *programname; 2575 char *dumpfile; 2576 char *dbname; 2577 char *dbname_tmp; 2578 char buf[BUFSIZ]; 2579 dump_version *load; 2580 int update, verbose; 2581 krb5_int32 crflags; 2582 int aindex; 2583 bool_t add_update = TRUE; 2584 + char iheader[MAX_HEADER]; 2585 uint32_t caller, last_sno, last_seconds, last_useconds; 2586 + kdb_log_context *log_ctx; 2587 2588 /* 2589 * Parse the arguments. 2590 */ 2591 programname = argv[0]; 2592 if (strrchr(programname, (int) '/')) 2593 programname = strrchr(argv[0], (int) '/') + 1; 2594 dumpfile = (char *) NULL; 2595 dbname = global_params.dbname; 2596 load = NULL; 2597 update = 0; 2598 verbose = 0; 2599 crflags = KRB5_KDB_CREATE_BTREE; 2600 exit_status = 0; 2601 dbname_tmp = (char *) NULL; 2602 tmppol_db = NULL; 2603 + log_ctx = util_context->kdblog_context; 2604 + 2605 for (aindex = 1; aindex < argc; aindex++) { 2606 if (strcmp(argv[aindex], oldoption) == 0) 2607 load = &old_version; 2608 else if (strcmp(argv[aindex], b6option) == 0) 2609 load = &beta6_version; 2610 else if (strcmp(argv[aindex], ovoption) == 0) 2611 load = &ov_version; 2612 + else if (!strcmp(argv[aindex], ipropoption)) { 2613 + if (log_ctx && log_ctx->iproprole) { 2614 + load = &iprop_version; 2615 + add_update = FALSE; 2616 + } else { 2617 + fprintf(stderr, gettext("Iprop not enabled\n")); 2618 + exit_status++; 2619 + return; 2620 + } 2621 } else if (strcmp(argv[aindex], verboseoption) == 0) 2622 verbose = 1; 2623 else if (strcmp(argv[aindex], updateoption) == 0) 2624 update = 1; 2625 else if (!strcmp(argv[aindex], hashoption)) 2626 crflags = KRB5_KDB_CREATE_HASH; 2627 else 2628 break; 2629 } 2630 if ((argc - aindex) != 1) { 2631 usage(); 2632 return; 2633 } 2634 dumpfile = argv[aindex]; 2635 2636 if (!(dbname_tmp = (char *) malloc(strlen(dbname)+ 2637 strlen(dump_tmptrail)+1))) { 2638 fprintf(stderr, gettext(no_name_mem_fmt), argv[0]); 2639 exit_status++; 2640 return; 2641 } 2642 strcpy(dbname_tmp, dbname); 2643 strcat(dbname_tmp, dump_tmptrail); 2644 2645 /* 2646 * Initialize the Kerberos context and error tables. 2647 */ 2648 if ((kret = krb5_init_context(&kcontext))) { 2649 fprintf(stderr, gettext(ctx_err_fmt), programname); 2650 free(dbname_tmp); 2651 exit_status++; 2652 return; 2653 } 2654 + 2655 + if (log_ctx && log_ctx->iproprole) 2656 + kcontext->kdblog_context = (void *)log_ctx; 2657 + 2658 /* 2659 * Open the dumpfile 2660 */ 2661 if (dumpfile) { 2662 if ((f = fopen(dumpfile, "r+")) == NULL) { 2663 fprintf(stderr, gettext(dfile_err_fmt), 2664 programname, dumpfile, 2665 error_message(errno)); 2666 exit_status++; 2667 return; 2668 } 2669 if ((kret = krb5_lock_file(kcontext, fileno(f), 2670 KRB5_LOCKMODE_SHARED))) { 2671 fprintf(stderr, gettext("%s: Cannot lock %s: %s\n"), programname, 2672 dumpfile, error_message(errno)); 2673 exit_status++; 2674 return; 2675 } 2676 } else 2677 f = stdin; 2678 2679 /* 2680 * Auto-detect dump version if we weren't told, verify if we were 2681 * told. 2682 */ 2683 fgets(buf, sizeof(buf), f); 2684 if (load) { 2685 /* 2686 * only check what we know; some headers only contain a 2687 * prefix 2688 */ 2689 if (strncmp(buf, load->header, strlen(load->header)) != 0) { 2690 fprintf(stderr, gettext(head_bad_fmt), 2691 programname, dumpfile); 2692 exit_status++; 2693 if (dumpfile) 2694 fclose(f); 2695 return; 2696 } 2697 } else { 2698 /* perhaps this should be in an array, but so what? */ 2699 if (strcmp(buf, old_version.header) == 0) 2700 load = &old_version; 2701 else if (strcmp(buf, beta6_version.header) == 0) 2702 load = &beta6_version; 2703 else if (strcmp(buf, beta7_version.header) == 0) 2704 load = &beta7_version; 2705 else if (strncmp(buf, ov_version.header, 2706 strlen(ov_version.header)) == 0) 2707 load = &ov_version; 2708 else { 2709 fprintf(stderr, gettext(head_bad_fmt), 2710 programname, dumpfile); 2711 exit_status++; 2712 if (dumpfile) 2713 fclose(f); 2714 return; 2715 } 2716 } 2717 if (load->updateonly && !update) { 2718 fprintf(stderr, 2719 gettext("%s: dump version %s can only " 2720 "be loaded with the -update flag\n"), 2721 programname, load->name); 2722 exit_status++; 2723 return; 2724 } 2725 /* 2726 * Cons up params for the new databases. If we are not in update 2727 * mode use a temp name that we'll rename later. 2728 */ 2729 newparams = global_params; 2730 if (! update) { 2731 newparams.mask |= KADM5_CONFIG_DBNAME; 2732 newparams.dbname = dbname_tmp; 2733 2734 if ((kret = kadm5_get_config_params(kcontext, NULL, NULL, 2735 &newparams, &newparams))) { 2736 com_err(argv[0], kret, 2737 gettext("while retreiving new " 2738 "configuration parameters")); 2739 exit_status++; 2740 return; 2741 } 2742 } 2743 /* 2744 * If not an update restoration, create the temp database. Always 2745 * create a temp policy db, even if we are not loading a dump file 2746 * with policy info, because they may be loading an old dump 2747 * intending to use it with the new kadm5 system. 2748 */ 2749 if (!update && ((kret = krb5_db_create(kcontext, dbname_tmp, crflags)))) { 2750 fprintf(stderr, gettext(dbcreaterr_fmt), 2751 programname, dbname_tmp, error_message(kret)); 2752 exit_status++; 2753 kadm5_free_config_params(kcontext, &newparams); 2754 if (dumpfile) fclose(f); 2755 return; 2756 } 2757 if (!update && (kret = osa_adb_create_policy_db(&newparams))) { 2758 fprintf(stderr, 2759 gettext("%s: %s while creating policy database\n"), 2760 programname, error_message(kret)); 2761 exit_status++; 2762 kadm5_free_config_params(kcontext, &newparams); 2763 if (dumpfile) 2764 fclose(f); 2765 return; 2766 } 2767 /* 2768 * Point ourselves at the new databases. 2769 */ 2770 if ((kret = krb5_db_set_name(kcontext, 2771 (update) ? dbname : dbname_tmp))) { 2772 fprintf(stderr, gettext(dbname_err_fmt), 2773 programname, 2774 (update) ? dbname : dbname_tmp, error_message(kret)); 2775 exit_status++; 2776 goto error; 2777 } 2778 if ((kret = osa_adb_open_policy(&tmppol_db, &newparams))) { 2779 fprintf(stderr, 2780 gettext("%s: %s while opening policy database\n"), 2781 programname, error_message(kret)); 2782 exit_status++; 2783 goto error; 2784 } 2785 /* 2786 * If an update restoration, make sure the db is left unusable if 2787 * the update fails. 2788 */ 2789 if (update) { 2790 if ((kret = osa_adb_get_lock(tmppol_db, OSA_ADB_PERMANENT))) { 2791 fprintf(stderr, 2792 gettext("%s: %s while " 2793 "permanently locking database\n"), 2794 programname, error_message(kret)); 2795 exit_status++; 2796 goto error; 2797 } 2798 } 2799 2800 /* 2801 * Initialize the database. 2802 */ 2803 if ((kret = krb5_db_init(kcontext))) { 2804 fprintf(stderr, gettext(dbinit_err_fmt), 2805 programname, error_message(kret)); 2806 exit_status++; 2807 goto error; 2808 } 2809 /* 2810 * grab an extra lock, since there are no other users 2811 */ 2812 if (!update) { 2813 kret = krb5_db_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE); 2814 if (kret) { 2815 fprintf(stderr, gettext(dblock_err_fmt), 2816 programname, error_message(kret)); 2817 exit_status++; 2818 goto error; 2819 } 2820 } 2821 + 2822 + if (log_ctx && log_ctx->iproprole) { 2823 + if (add_update) 2824 + caller = FKCOMMAND; 2825 + else 2826 + caller = FKPROPD; 2827 + 2828 + if (ulog_map(kcontext, &global_params, caller)) { 2829 + fprintf(stderr, 2830 + gettext("%s: Could not map log\n"), 2831 + programname); 2832 + exit_status++; 2833 + goto error; 2834 + } 2835 + 2836 + /* 2837 + * We don't want to take out the ulog out from underneath 2838 + * kadmind so we reinit the header log. 2839 + * 2840 + * We also don't want to add to the update log since we 2841 + * are doing a whole sale replace of the db, because: 2842 + * we could easily exceed # of update entries 2843 + * we could implicity delete db entries during a replace 2844 + * no advantage in incr updates when entire db is replaced 2845 + */ 2846 + if (!update) { 2847 + memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t)); 2848 + 2849 + log_ctx->ulog->kdb_hmagic = KDB_HMAGIC; 2850 + log_ctx->ulog->db_version_num = KDB_VERSION; 2851 + log_ctx->ulog->kdb_state = KDB_STABLE; 2852 + log_ctx->ulog->kdb_block = ULOG_BLOCK; 2853 + 2854 + log_ctx->iproprole = IPROP_NULL; 2855 + 2856 + if (!add_update) { 2857 + sscanf(buf, "%s %u %u %u", iheader, &last_sno, 2858 + &last_seconds, &last_useconds); 2859 + 2860 + log_ctx->ulog->kdb_last_sno = last_sno; 2861 + log_ctx->ulog->kdb_last_time.seconds = 2862 + last_seconds; 2863 + log_ctx->ulog->kdb_last_time.useconds = 2864 + last_useconds; 2865 + } 2866 + } 2867 + } 2868 2869 if (restore_dump(programname, kcontext, 2870 (dumpfile) ? dumpfile : stdin_name, 2871 f, verbose, load, tmppol_db)) { 2872 fprintf(stderr, gettext(restfail_fmt), 2873 programname, load->name); 2874 exit_status++; 2875 } 2876 if (!update && (kret = krb5_db_unlock(kcontext))) { 2877 /* change this error? */ 2878 fprintf(stderr, gettext(dbunlockerr_fmt), 2879 programname, dbname_tmp, error_message(kret)); 2880 exit_status++; 2881 } 2882 if ((kret = krb5_db_fini(kcontext))) { 2883 fprintf(stderr, gettext(close_err_fmt), 2884 programname, error_message(kret)); 2885 exit_status++; 2886 } 2887 2888 if (!update && load->create_kadm5 && 2889 ((kret = kadm5_create_magic_princs(&newparams, kcontext)))) { 2890 /* error message printed by create_magic_princs */ 2891 exit_status++; 2892 } 2893 2894 /* close policy db below */ 2895 2896 error: 2897 /* 2898 * If not an update: if there was an error, destroy the temp 2899 * database, otherwise rename it into place. 2900 * 2901 * If an update: if there was no error, unlock the database. 2902 */ 2903 if (!update) { 2904 if (exit_status) { 2905 if ((kret = 2906 krb5_db_destroy(kcontext, dbname_tmp))) { 2907 fprintf(stderr, gettext(dbdelerr_fmt), 2908 programname, dbname_tmp, 2909 error_message(kret)); 2910 exit_status++; 2911 } 2912 if ((kret = osa_adb_destroy_policy_db(&newparams))) { 2913 fprintf(stderr, 2914 gettext("%s: %s while destroying " 2915 "policy database\n"), 2916 programname, error_message(kret)); 2917 exit_status++; 2918 } 2919 } else { 2920 if ((kret = krb5_db_rename(kcontext, 2921 dbname_tmp, 2922 dbname))) { 2923 fprintf(stderr, gettext(dbrenerr_fmt), 2924 programname, dbname_tmp, dbname, 2925 error_message(kret)); 2926 exit_status++; 2927 } 2928 if ((kret = osa_adb_close_policy(tmppol_db))) { 2929 fprintf(stderr, gettext(close_err_fmt), 2930 programname, error_message(kret)); 2931 exit_status++; 2932 } 2933 if ((kret = osa_adb_rename_policy_db(&newparams, 2934 &global_params))) { 2935 fprintf(stderr, 2936 gettext("%s: %s while renaming " 2937 "policy db %s to %s\n"), 2938 programname, error_message(kret), 2939 newparams.admin_dbname, 2940 global_params.admin_dbname); 2941 exit_status++; 2942 } 2943 } 2944 } else { /* update */ 2945 if (!exit_status && ((kret = osa_adb_release_lock(tmppol_db)))) { 2946 fprintf(stderr, 2947 gettext("%s: %s while releasing permanent lock\n"), 2948 programname, error_message(kret)); 2949 exit_status++; 2950 } 2951 if (tmppol_db && ((kret = osa_adb_close_policy(tmppol_db)))) { 2952 fprintf(stderr, gettext(close_err_fmt), 2953 programname, error_message(kret)); 2954 exit_status++; 2955 } 2956 } 2957 2958 if (dumpfile) { 2959 (void) krb5_lock_file(kcontext, 2960 fileno(f), KRB5_LOCKMODE_UNLOCK); 2961 fclose(f); 2962 } 2963 if (dbname_tmp) 2964 free(dbname_tmp); 2965 krb5_free_context(kcontext); 2966 } ----Unchanged portion omitted----