1 /* $NetBSD: verify_krb5_conf.c,v 1.1.1.2 2014/04/24 12:45:51 pettai Exp $ */
4 * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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
36 #include "krb5_locl.h"
37 #include <krb5/getarg.h>
38 #include <krb5/parse_bytes.h>
41 /* verify krb5.conf */
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;
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
,
63 sizeof(args
)/sizeof(*args
),
70 check_bytes(krb5_context context
, const char *path
, char *data
)
72 if(parse_bytes(data
, NULL
) == -1) {
73 krb5_warnx(context
, "%s: failed to parse \"%s\" as size", path
, data
);
80 check_time(krb5_context context
, const char *path
, char *data
)
82 if(parse_time(data
, NULL
) == -1) {
83 krb5_warnx(context
, "%s: failed to parse \"%s\" as time", path
, data
);
90 check_numeric(krb5_context context
, const char *path
, char *data
)
94 v
= strtol(data
, &end
, 0);
96 if ((v
== LONG_MIN
|| v
== LONG_MAX
) && errno
!= 0) {
97 krb5_warnx(context
, "%s: over/under flow for \"%s\"",
102 krb5_warnx(context
, "%s: failed to parse \"%s\" as a number",
110 check_boolean(krb5_context context
, const char *path
, char *data
)
114 if(strcasecmp(data
, "yes") == 0 ||
115 strcasecmp(data
, "true") == 0 ||
116 strcasecmp(data
, "no") == 0 ||
117 strcasecmp(data
, "false") == 0)
119 v
= strtol(data
, &end
, 0);
121 krb5_warnx(context
, "%s: failed to parse \"%s\" as a boolean",
126 krb5_warnx(context
, "%s: numeric value \"%s\" is treated as \"true\"",
132 check_524(krb5_context context
, const char *path
, char *data
)
134 if(strcasecmp(data
, "yes") == 0 ||
135 strcasecmp(data
, "no") == 0 ||
136 strcasecmp(data
, "2b") == 0 ||
137 strcasecmp(data
, "local") == 0)
140 krb5_warnx(context
, "%s: didn't contain a valid option `%s'",
146 check_host(krb5_context context
, const char *path
, char *data
)
150 const char *p
= data
;
151 struct addrinfo hints
;
157 hints
.ai_family
= PF_UNSPEC
;
158 hints
.ai_socktype
= 0;
159 hints
.ai_protocol
= 0;
161 hints
.ai_addrlen
= 0;
162 hints
.ai_canonname
= NULL
;
163 hints
.ai_addr
= NULL
;
164 hints
.ai_next
= NULL
;
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){
170 hints
.ai_socktype
= SOCK_STREAM
;
171 strlcpy(service
, "http", sizeof(service
));
173 } else if(strncmp(p
, "http/", 5) == 0) {
175 hints
.ai_socktype
= SOCK_STREAM
;
176 strlcpy(service
, "http", sizeof(service
));
178 }else if(strncmp(p
, "tcp/", 4) == 0){
180 hints
.ai_socktype
= SOCK_STREAM
;
181 strlcpy(service
, "kerberos", sizeof(service
));
183 } else if(strncmp(p
, "udp/", 4) == 0) {
185 hints
.ai_socktype
= SOCK_DGRAM
;
186 strlcpy(service
, "kerberos", sizeof(service
));
189 hints
.ai_socktype
= SOCK_DGRAM
;
190 strlcpy(service
, "kerberos", sizeof(service
));
193 if(strsep_copy(&p
, ":", hostname
, sizeof(hostname
)) < 0) {
196 hostname
[strcspn(hostname
, "/")] = '\0';
199 int tmp
= strtol(p
, &end
, 0);
201 krb5_warnx(context
, "%s: failed to parse port number in %s",
206 snprintf(service
, sizeof(service
), "%u", defport
);
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
);
214 krb5_warnx(context
, "%s: %s (%s)", path
, gai_strerror(ret
), hostname
);
221 mit_entry(krb5_context context
, const char *path
, char *data
)
223 if (warn_mit_syntax_flag
)
224 krb5_warnx(context
, "%s is only used by MIT Kerberos", path
);
233 #define L(X) { #X, LOG_ ## X }
235 static struct s2i syslogvals
[] = {
280 find_value(const char *s
, struct s2i
*table
)
282 while(table
->s
&& strcasecmp(table
->s
, s
))
288 check_log(krb5_context context
, const char *path
, char *data
)
290 /* XXX sync with log.c */
291 int min
= 0, max
= -1, n
;
293 const char *p
= data
;
295 n
= sscanf(p
, "%d%c%d/", &min
, &c
, &max
);
309 krb5_warnx(context
, "%s: failed to parse \"%s\"", path
, data
);
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] == '='))
319 if(strncmp(p
, "SYSLOG", 6) == 0){
321 char severity
[128] = "";
322 char facility
[128] = "";
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\"",
337 if(find_value(severity
, syslogvals
) == -1) {
338 krb5_warnx(context
, "%s: unknown syslog severity \"%s\"",
344 krb5_warnx(context
, "%s: unknown log type: \"%s\"", path
, data
);
349 typedef int (*check_func_t
)(krb5_context
, const char*, char*);
357 struct entry all_strings
[] = {
358 { "", krb5_config_string
, NULL
},
362 struct entry all_boolean
[] = {
363 { "", krb5_config_string
, check_boolean
},
368 struct entry v4_name_convert_entries
[] = {
369 { "host", krb5_config_list
, all_strings
},
370 { "plain", krb5_config_list
, all_strings
},
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
},
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
},
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
},
444 { "anonymous", krb5_config_string
, check_boolean
},
446 { "", krb5_config_list
, appdefaults_entries
},
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
},
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
},
483 struct entry realms_foobar
[] = {
484 { "", krb5_config_list
, realms_entries
},
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
},
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
, 1 },
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
},
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
},
538 struct entry log_strings
[] = {
539 { "", krb5_config_string
, check_log
},
545 struct entry kdcdefaults_entries
[] = {
546 { "kdc_ports", krb5_config_string
, mit_entry
},
547 { "v4_mode", krb5_config_string
, mit_entry
},
551 struct entry capaths_entries
[] = {
552 { "", krb5_config_list
, all_strings
},
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
},
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
},
577 { "kdcdefaults", krb5_config_list
, kdcdefaults_entries
},
583 check_section(krb5_context context
, const char *path
, krb5_config_section
*cf
,
584 struct entry
*entries
)
587 krb5_config_section
*p
;
592 for(p
= cf
; p
!= NULL
; p
= p
->next
) {
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
);
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
);
607 krb5_warnx(context
, "%s: is a deprecated entry", local
);
613 if(e
->name
== NULL
) {
614 krb5_warnx(context
, "%s: unknown entry", local
);
624 dumpconfig(int level
, krb5_config_section
*top
)
626 krb5_config_section
*x
;
627 for(x
= top
; x
; x
= x
->next
) {
629 case krb5_config_list
:
631 printf("[%s]\n", x
->name
);
633 printf("%*s%s = {\n", 4 * level
, " ", x
->name
);
635 dumpconfig(level
+ 1, x
->u
.list
);
637 printf("%*s}\n", 4 * level
, " ");
639 case krb5_config_string
:
640 printf("%*s%s = %s\n", 4 * level
, " ", x
->name
, x
->u
.string
);
647 main(int argc
, char **argv
)
649 krb5_context context
;
651 krb5_config_section
*tmp_cf
;
654 setprogname (argv
[0]);
656 ret
= krb5_init_context(&context
);
657 if (ret
== KRB5_CONFIG_BADFORMAT
)
658 errx (1, "krb5_init_context failed to parse configuration file");
660 errx (1, "krb5_init_context failed with %d", ret
);
662 if(getarg(args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
, &optidx
))
678 krb5_get_default_config_files(&argv
);
681 ret
= krb5_config_parse_file_multi(context
, *argv
, &tmp_cf
);
683 krb5_warn (context
, ret
, "krb5_config_parse_file");
688 dumpconfig(0, tmp_cf
);
690 return check_section(context
, "", tmp_cf
, toplevel_sections
);