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