1 /* 2 * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "krb5_locl.h" 35 #include <getarg.h> 36 #include <parse_bytes.h> 37 #include <err.h> 38 39 /* verify krb5.conf */ 40 41 static int dumpconfig_flag = 0; 42 static int version_flag = 0; 43 static int help_flag = 0; 44 static int warn_mit_syntax_flag = 0; 45 46 static struct getargs args[] = { 47 {"dumpconfig", 0, arg_flag, &dumpconfig_flag, 48 "show the parsed config files", NULL }, 49 {"warn-mit-syntax", 0, arg_flag, &warn_mit_syntax_flag, 50 "show the parsed config files", NULL }, 51 {"version", 0, arg_flag, &version_flag, 52 "print version", NULL }, 53 {"help", 0, arg_flag, &help_flag, 54 NULL, NULL } 55 }; 56 57 static void 58 usage (int ret) 59 { 60 arg_printusage (args, 61 sizeof(args)/sizeof(*args), 62 NULL, 63 "[config-file]"); 64 exit (ret); 65 } 66 67 static int 68 check_bytes(krb5_context context, const char *path, char *data) 69 { 70 if(parse_bytes(data, NULL) == -1) { 71 krb5_warnx(context, "%s: failed to parse \"%s\" as size", path, data); 72 return 1; 73 } 74 return 0; 75 } 76 77 static int 78 check_time(krb5_context context, const char *path, char *data) 79 { 80 if(parse_time(data, NULL) == -1) { 81 krb5_warnx(context, "%s: failed to parse \"%s\" as time", path, data); 82 return 1; 83 } 84 return 0; 85 } 86 87 static int 88 check_numeric(krb5_context context, const char *path, char *data) 89 { 90 long v; 91 char *end; 92 v = strtol(data, &end, 0); 93 94 if ((v == LONG_MIN || v == LONG_MAX) && errno != 0) { 95 krb5_warnx(context, "%s: over/under flow for \"%s\"", 96 path, data); 97 return 1; 98 } 99 if(*end != '\0') { 100 krb5_warnx(context, "%s: failed to parse \"%s\" as a number", 101 path, data); 102 return 1; 103 } 104 return 0; 105 } 106 107 static int 108 check_boolean(krb5_context context, const char *path, char *data) 109 { 110 long int v; 111 char *end; 112 if(strcasecmp(data, "yes") == 0 || 113 strcasecmp(data, "true") == 0 || 114 strcasecmp(data, "no") == 0 || 115 strcasecmp(data, "false") == 0) 116 return 0; 117 v = strtol(data, &end, 0); 118 if(*end != '\0') { 119 krb5_warnx(context, "%s: failed to parse \"%s\" as a boolean", 120 path, data); 121 return 1; 122 } 123 if(v != 0 && v != 1) 124 krb5_warnx(context, "%s: numeric value \"%s\" is treated as \"true\"", 125 path, data); 126 return 0; 127 } 128 129 static int 130 check_524(krb5_context context, const char *path, char *data) 131 { 132 if(strcasecmp(data, "yes") == 0 || 133 strcasecmp(data, "no") == 0 || 134 strcasecmp(data, "2b") == 0 || 135 strcasecmp(data, "local") == 0) 136 return 0; 137 138 krb5_warnx(context, "%s: didn't contain a valid option `%s'", 139 path, data); 140 return 1; 141 } 142 143 static int 144 check_host(krb5_context context, const char *path, char *data) 145 { 146 int ret; 147 char hostname[128]; 148 const char *p = data; 149 struct addrinfo hints; 150 char service[32]; 151 int defport; 152 struct addrinfo *ai; 153 154 hints.ai_flags = 0; 155 hints.ai_family = PF_UNSPEC; 156 hints.ai_socktype = 0; 157 hints.ai_protocol = 0; 158 159 hints.ai_addrlen = 0; 160 hints.ai_canonname = NULL; 161 hints.ai_addr = NULL; 162 hints.ai_next = NULL; 163 164 /* XXX data could be a list of hosts that this code can't handle */ 165 /* XXX copied from krbhst.c */ 166 if(strncmp(p, "http://", 7) == 0){ 167 p += 7; 168 hints.ai_socktype = SOCK_STREAM; 169 strlcpy(service, "http", sizeof(service)); 170 defport = 80; 171 } else if(strncmp(p, "http/", 5) == 0) { 172 p += 5; 173 hints.ai_socktype = SOCK_STREAM; 174 strlcpy(service, "http", sizeof(service)); 175 defport = 80; 176 }else if(strncmp(p, "tcp/", 4) == 0){ 177 p += 4; 178 hints.ai_socktype = SOCK_STREAM; 179 strlcpy(service, "kerberos", sizeof(service)); 180 defport = 88; 181 } else if(strncmp(p, "udp/", 4) == 0) { 182 p += 4; 183 hints.ai_socktype = SOCK_DGRAM; 184 strlcpy(service, "kerberos", sizeof(service)); 185 defport = 88; 186 } else { 187 hints.ai_socktype = SOCK_DGRAM; 188 strlcpy(service, "kerberos", sizeof(service)); 189 defport = 88; 190 } 191 if(strsep_copy(&p, ":", hostname, sizeof(hostname)) < 0) { 192 return 1; 193 } 194 hostname[strcspn(hostname, "/")] = '\0'; 195 if(p != NULL) { 196 char *end; 197 int tmp = strtol(p, &end, 0); 198 if(end == p) { 199 krb5_warnx(context, "%s: failed to parse port number in %s", 200 path, data); 201 return 1; 202 } 203 defport = tmp; 204 snprintf(service, sizeof(service), "%u", defport); 205 } 206 ret = getaddrinfo(hostname, service, &hints, &ai); 207 if(ret == EAI_SERVICE && !isdigit((unsigned char)service[0])) { 208 snprintf(service, sizeof(service), "%u", defport); 209 ret = getaddrinfo(hostname, service, &hints, &ai); 210 } 211 if(ret != 0) { 212 krb5_warnx(context, "%s: %s (%s)", path, gai_strerror(ret), hostname); 213 return 1; 214 } 215 return 0; 216 } 217 218 static int 219 mit_entry(krb5_context context, const char *path, char *data) 220 { 221 if (warn_mit_syntax_flag) 222 krb5_warnx(context, "%s is only used by MIT Kerberos", path); 223 return 0; 224 } 225 226 struct s2i { 227 const char *s; 228 int val; 229 }; 230 231 #define L(X) { #X, LOG_ ## X } 232 233 static struct s2i syslogvals[] = { 234 /* severity */ 235 L(EMERG), 236 L(ALERT), 237 L(CRIT), 238 L(ERR), 239 L(WARNING), 240 L(NOTICE), 241 L(INFO), 242 L(DEBUG), 243 /* facility */ 244 L(AUTH), 245 #ifdef LOG_AUTHPRIV 246 L(AUTHPRIV), 247 #endif 248 #ifdef LOG_CRON 249 L(CRON), 250 #endif 251 L(DAEMON), 252 #ifdef LOG_FTP 253 L(FTP), 254 #endif 255 L(KERN), 256 L(LPR), 257 L(MAIL), 258 #ifdef LOG_NEWS 259 L(NEWS), 260 #endif 261 L(SYSLOG), 262 L(USER), 263 #ifdef LOG_UUCP 264 L(UUCP), 265 #endif 266 L(LOCAL0), 267 L(LOCAL1), 268 L(LOCAL2), 269 L(LOCAL3), 270 L(LOCAL4), 271 L(LOCAL5), 272 L(LOCAL6), 273 L(LOCAL7), 274 { NULL, -1 } 275 }; 276 277 static int 278 find_value(const char *s, struct s2i *table) 279 { 280 while(table->s && strcasecmp(table->s, s)) 281 table++; 282 return table->val; 283 } 284 285 static int 286 check_log(krb5_context context, const char *path, char *data) 287 { 288 /* XXX sync with log.c */ 289 int min = 0, max = -1, n; 290 char c; 291 const char *p = data; 292 293 n = sscanf(p, "%d%c%d/", &min, &c, &max); 294 if(n == 2){ 295 if(c == '/') { 296 if(min < 0){ 297 max = -min; 298 min = 0; 299 }else{ 300 max = min; 301 } 302 } 303 } 304 if(n){ 305 p = strchr(p, '/'); 306 if(p == NULL) { 307 krb5_warnx(context, "%s: failed to parse \"%s\"", path, data); 308 return 1; 309 } 310 p++; 311 } 312 if(strcmp(p, "STDERR") == 0 || 313 strcmp(p, "CONSOLE") == 0 || 314 (strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')) || 315 (strncmp(p, "DEVICE", 6) == 0 && p[6] == '=')) 316 return 0; 317 if(strncmp(p, "SYSLOG", 6) == 0){ 318 int ret = 0; 319 char severity[128] = ""; 320 char facility[128] = ""; 321 p += 6; 322 if(*p != '\0') 323 p++; 324 if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1) 325 strsep_copy(&p, ":", facility, sizeof(facility)); 326 if(*severity == '\0') 327 strlcpy(severity, "ERR", sizeof(severity)); 328 if(*facility == '\0') 329 strlcpy(facility, "AUTH", sizeof(facility)); 330 if(find_value(severity, syslogvals) == -1) { 331 krb5_warnx(context, "%s: unknown syslog facility \"%s\"", 332 path, facility); 333 ret++; 334 } 335 if(find_value(severity, syslogvals) == -1) { 336 krb5_warnx(context, "%s: unknown syslog severity \"%s\"", 337 path, severity); 338 ret++; 339 } 340 return ret; 341 }else{ 342 krb5_warnx(context, "%s: unknown log type: \"%s\"", path, data); 343 return 1; 344 } 345 } 346 347 typedef int (*check_func_t)(krb5_context, const char*, char*); 348 struct entry { 349 const char *name; 350 int type; 351 void *check_data; 352 int deprecated; 353 }; 354 355 struct entry all_strings[] = { 356 { "", krb5_config_string, NULL }, 357 { NULL } 358 }; 359 360 struct entry all_boolean[] = { 361 { "", krb5_config_string, check_boolean }, 362 { NULL } 363 }; 364 365 366 struct entry v4_name_convert_entries[] = { 367 { "host", krb5_config_list, all_strings }, 368 { "plain", krb5_config_list, all_strings }, 369 { NULL } 370 }; 371 372 struct entry libdefaults_entries[] = { 373 { "accept_null_addresses", krb5_config_string, check_boolean }, 374 { "allow_weak_crypto", krb5_config_string, check_boolean }, 375 { "capath", krb5_config_list, all_strings, 1 }, 376 { "check_pac", krb5_config_string, check_boolean }, 377 { "clockskew", krb5_config_string, check_time }, 378 { "date_format", krb5_config_string, NULL }, 379 { "default_cc_name", krb5_config_string, NULL }, 380 { "default_etypes", krb5_config_string, NULL }, 381 { "default_etypes_des", krb5_config_string, NULL }, 382 { "default_keytab_modify_name", krb5_config_string, NULL }, 383 { "default_keytab_name", krb5_config_string, NULL }, 384 { "default_realm", krb5_config_string, NULL }, 385 { "dns_canonize_hostname", krb5_config_string, check_boolean }, 386 { "dns_proxy", krb5_config_string, NULL }, 387 { "dns_lookup_kdc", krb5_config_string, check_boolean }, 388 { "dns_lookup_realm", krb5_config_string, check_boolean }, 389 { "dns_lookup_realm_labels", krb5_config_string, NULL }, 390 { "egd_socket", krb5_config_string, NULL }, 391 { "encrypt", krb5_config_string, check_boolean }, 392 { "extra_addresses", krb5_config_string, NULL }, 393 { "fcache_version", krb5_config_string, check_numeric }, 394 { "fcc-mit-ticketflags", krb5_config_string, check_boolean }, 395 { "forward", krb5_config_string, check_boolean }, 396 { "forwardable", krb5_config_string, check_boolean }, 397 { "http_proxy", krb5_config_string, check_host /* XXX */ }, 398 { "ignore_addresses", krb5_config_string, NULL }, 399 { "kdc_timeout", krb5_config_string, check_time }, 400 { "kdc_timesync", krb5_config_string, check_boolean }, 401 { "log_utc", krb5_config_string, check_boolean }, 402 { "maxretries", krb5_config_string, check_numeric }, 403 { "scan_interfaces", krb5_config_string, check_boolean }, 404 { "srv_lookup", krb5_config_string, check_boolean }, 405 { "srv_try_txt", krb5_config_string, check_boolean }, 406 { "ticket_lifetime", krb5_config_string, check_time }, 407 { "time_format", krb5_config_string, NULL }, 408 { "transited_realms_reject", krb5_config_string, NULL }, 409 { "no-addresses", krb5_config_string, check_boolean }, 410 { "v4_instance_resolve", krb5_config_string, check_boolean }, 411 { "v4_name_convert", krb5_config_list, v4_name_convert_entries }, 412 { "verify_ap_req_nofail", krb5_config_string, check_boolean }, 413 { "max_retries", krb5_config_string, check_time }, 414 { "renew_lifetime", krb5_config_string, check_time }, 415 { "proxiable", krb5_config_string, check_boolean }, 416 { "warn_pwexpire", krb5_config_string, check_time }, 417 /* MIT stuff */ 418 { "permitted_enctypes", krb5_config_string, mit_entry }, 419 { "default_tgs_enctypes", krb5_config_string, mit_entry }, 420 { "default_tkt_enctypes", krb5_config_string, mit_entry }, 421 { NULL } 422 }; 423 424 struct entry appdefaults_entries[] = { 425 { "afslog", krb5_config_string, check_boolean }, 426 { "afs-use-524", krb5_config_string, check_524 }, 427 { "encrypt", krb5_config_string, check_boolean }, 428 { "forward", krb5_config_string, check_boolean }, 429 { "forwardable", krb5_config_string, check_boolean }, 430 { "proxiable", krb5_config_string, check_boolean }, 431 { "ticket_lifetime", krb5_config_string, check_time }, 432 { "renew_lifetime", krb5_config_string, check_time }, 433 { "no-addresses", krb5_config_string, check_boolean }, 434 { "krb4_get_tickets", krb5_config_string, check_boolean }, 435 { "pkinit_anchors", krb5_config_string, NULL }, 436 { "pkinit_win2k", krb5_config_string, NULL }, 437 { "pkinit_win2k_require_binding", krb5_config_string, NULL }, 438 { "pkinit_require_eku", krb5_config_string, NULL }, 439 { "pkinit_require_krbtgt_otherName", krb5_config_string, NULL }, 440 { "pkinit_require_hostname_match", krb5_config_string, NULL }, 441 #if 0 442 { "anonymous", krb5_config_string, check_boolean }, 443 #endif 444 { "", krb5_config_list, appdefaults_entries }, 445 { NULL } 446 }; 447 448 struct entry realms_entries[] = { 449 { "forwardable", krb5_config_string, check_boolean }, 450 { "proxiable", krb5_config_string, check_boolean }, 451 { "ticket_lifetime", krb5_config_string, check_time }, 452 { "renew_lifetime", krb5_config_string, check_time }, 453 { "warn_pwexpire", krb5_config_string, check_time }, 454 { "kdc", krb5_config_string, check_host }, 455 { "admin_server", krb5_config_string, check_host }, 456 { "kpasswd_server", krb5_config_string, check_host }, 457 { "krb524_server", krb5_config_string, check_host }, 458 { "v4_name_convert", krb5_config_list, v4_name_convert_entries }, 459 { "v4_instance_convert", krb5_config_list, all_strings }, 460 { "v4_domains", krb5_config_string, NULL }, 461 { "default_domain", krb5_config_string, NULL }, 462 { "win2k_pkinit", krb5_config_string, NULL }, 463 /* MIT stuff */ 464 { "admin_keytab", krb5_config_string, mit_entry }, 465 { "acl_file", krb5_config_string, mit_entry }, 466 { "dict_file", krb5_config_string, mit_entry }, 467 { "kadmind_port", krb5_config_string, mit_entry }, 468 { "kpasswd_port", krb5_config_string, mit_entry }, 469 { "master_key_name", krb5_config_string, mit_entry }, 470 { "master_key_type", krb5_config_string, mit_entry }, 471 { "key_stash_file", krb5_config_string, mit_entry }, 472 { "max_life", krb5_config_string, mit_entry }, 473 { "max_renewable_life", krb5_config_string, mit_entry }, 474 { "default_principal_expiration", krb5_config_string, mit_entry }, 475 { "default_principal_flags", krb5_config_string, mit_entry }, 476 { "supported_enctypes", krb5_config_string, mit_entry }, 477 { "database_name", krb5_config_string, mit_entry }, 478 { NULL } 479 }; 480 481 struct entry realms_foobar[] = { 482 { "", krb5_config_list, realms_entries }, 483 { NULL } 484 }; 485 486 487 struct entry kdc_database_entries[] = { 488 { "realm", krb5_config_string, NULL }, 489 { "dbname", krb5_config_string, NULL }, 490 { "mkey_file", krb5_config_string, NULL }, 491 { "acl_file", krb5_config_string, NULL }, 492 { "log_file", krb5_config_string, NULL }, 493 { NULL } 494 }; 495 496 struct entry kdc_entries[] = { 497 { "database", krb5_config_list, kdc_database_entries }, 498 { "key-file", krb5_config_string, NULL }, 499 { "logging", krb5_config_string, check_log }, 500 { "max-request", krb5_config_string, check_bytes }, 501 { "require-preauth", krb5_config_string, check_boolean }, 502 { "ports", krb5_config_string, NULL }, 503 { "addresses", krb5_config_string, NULL }, 504 { "enable-kerberos4", krb5_config_string, check_boolean }, 505 { "enable-524", krb5_config_string, check_boolean }, 506 { "enable-http", krb5_config_string, check_boolean }, 507 { "check-ticket-addresses", krb5_config_string, check_boolean }, 508 { "allow-null-ticket-addresses", krb5_config_string, check_boolean }, 509 { "allow-anonymous", krb5_config_string, check_boolean }, 510 { "v4_realm", krb5_config_string, NULL }, 511 { "enable-kaserver", krb5_config_string, check_boolean, 1 }, 512 { "encode_as_rep_as_tgs_rep", krb5_config_string, check_boolean }, 513 { "kdc_warn_pwexpire", krb5_config_string, check_time }, 514 { "use_2b", krb5_config_list, NULL }, 515 { "enable-pkinit", krb5_config_string, check_boolean }, 516 { "pkinit_identity", krb5_config_string, NULL }, 517 { "pkinit_anchors", krb5_config_string, NULL }, 518 { "pkinit_pool", krb5_config_string, NULL }, 519 { "pkinit_revoke", krb5_config_string, NULL }, 520 { "pkinit_kdc_ocsp", krb5_config_string, NULL }, 521 { "pkinit_principal_in_certificate", krb5_config_string, NULL }, 522 { "pkinit_dh_min_bits", krb5_config_string, NULL }, 523 { "pkinit_allow_proxy_certificate", krb5_config_string, NULL }, 524 { "hdb-ldap-create-base", krb5_config_string, NULL }, 525 { "v4-realm", krb5_config_string, NULL }, 526 { NULL } 527 }; 528 529 struct entry kadmin_entries[] = { 530 { "password_lifetime", krb5_config_string, check_time }, 531 { "default_keys", krb5_config_string, NULL }, 532 { "use_v4_salt", krb5_config_string, NULL }, 533 { "require-preauth", krb5_config_string, check_boolean }, 534 { NULL } 535 }; 536 struct entry log_strings[] = { 537 { "", krb5_config_string, check_log }, 538 { NULL } 539 }; 540 541 542 /* MIT stuff */ 543 struct entry kdcdefaults_entries[] = { 544 { "kdc_ports", krb5_config_string, mit_entry }, 545 { "v4_mode", krb5_config_string, mit_entry }, 546 { NULL } 547 }; 548 549 struct entry capaths_entries[] = { 550 { "", krb5_config_list, all_strings }, 551 { NULL } 552 }; 553 554 struct entry password_quality_entries[] = { 555 { "policies", krb5_config_string, NULL }, 556 { "external_program", krb5_config_string, NULL }, 557 { "min_classes", krb5_config_string, check_numeric }, 558 { "min_length", krb5_config_string, check_numeric }, 559 { "", krb5_config_list, all_strings }, 560 { NULL } 561 }; 562 563 struct entry toplevel_sections[] = { 564 { "libdefaults" , krb5_config_list, libdefaults_entries }, 565 { "realms", krb5_config_list, realms_foobar }, 566 { "domain_realm", krb5_config_list, all_strings }, 567 { "logging", krb5_config_list, log_strings }, 568 { "kdc", krb5_config_list, kdc_entries }, 569 { "kadmin", krb5_config_list, kadmin_entries }, 570 { "appdefaults", krb5_config_list, appdefaults_entries }, 571 { "gssapi", krb5_config_list, NULL }, 572 { "capaths", krb5_config_list, capaths_entries }, 573 { "password_quality", krb5_config_list, password_quality_entries }, 574 /* MIT stuff */ 575 { "kdcdefaults", krb5_config_list, kdcdefaults_entries }, 576 { NULL } 577 }; 578 579 580 static int 581 check_section(krb5_context context, const char *path, krb5_config_section *cf, 582 struct entry *entries) 583 { 584 int error = 0; 585 krb5_config_section *p; 586 struct entry *e; 587 588 char *local; 589 590 for(p = cf; p != NULL; p = p->next) { 591 local = NULL; 592 if (asprintf(&local, "%s/%s", path, p->name) < 0 || local == NULL) 593 errx(1, "out of memory"); 594 for(e = entries; e->name != NULL; e++) { 595 if(*e->name == '\0' || strcmp(e->name, p->name) == 0) { 596 if(e->type != p->type) { 597 krb5_warnx(context, "%s: unknown or wrong type", local); 598 error |= 1; 599 } else if(p->type == krb5_config_string && e->check_data != NULL) { 600 error |= (*(check_func_t)e->check_data)(context, local, p->u.string); 601 } else if(p->type == krb5_config_list && e->check_data != NULL) { 602 error |= check_section(context, local, p->u.list, e->check_data); 603 } 604 if(e->deprecated) { 605 krb5_warnx(context, "%s: is a deprecated entry", local); 606 error |= 1; 607 } 608 break; 609 } 610 } 611 if(e->name == NULL) { 612 krb5_warnx(context, "%s: unknown entry", local); 613 error |= 1; 614 } 615 free(local); 616 } 617 return error; 618 } 619 620 621 static void 622 dumpconfig(int level, krb5_config_section *top) 623 { 624 krb5_config_section *x; 625 for(x = top; x; x = x->next) { 626 switch(x->type) { 627 case krb5_config_list: 628 if(level == 0) { 629 printf("[%s]\n", x->name); 630 } else { 631 printf("%*s%s = {\n", 4 * level, " ", x->name); 632 } 633 dumpconfig(level + 1, x->u.list); 634 if(level > 0) 635 printf("%*s}\n", 4 * level, " "); 636 break; 637 case krb5_config_string: 638 printf("%*s%s = %s\n", 4 * level, " ", x->name, x->u.string); 639 break; 640 } 641 } 642 } 643 644 int 645 main(int argc, char **argv) 646 { 647 krb5_context context; 648 krb5_error_code ret; 649 krb5_config_section *tmp_cf; 650 int optidx = 0; 651 652 setprogname (argv[0]); 653 654 ret = krb5_init_context(&context); 655 if (ret == KRB5_CONFIG_BADFORMAT) 656 errx (1, "krb5_init_context failed to parse configuration file"); 657 else if (ret) 658 errx (1, "krb5_init_context failed with %d", ret); 659 660 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 661 usage(1); 662 663 if (help_flag) 664 usage (0); 665 666 if(version_flag){ 667 print_version(NULL); 668 exit(0); 669 } 670 671 argc -= optidx; 672 argv += optidx; 673 674 tmp_cf = NULL; 675 if(argc == 0) 676 krb5_get_default_config_files(&argv); 677 678 while(*argv) { 679 ret = krb5_config_parse_file_multi(context, *argv, &tmp_cf); 680 if (ret != 0) 681 krb5_warn (context, ret, "krb5_config_parse_file"); 682 argv++; 683 } 684 685 if(dumpconfig_flag) 686 dumpconfig(0, tmp_cf); 687 688 return check_section(context, "", tmp_cf, toplevel_sections); 689 } 690