diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /third_party/heimdal/lib/krb5/verify_krb5_conf.c | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/heimdal/lib/krb5/verify_krb5_conf.c')
-rw-r--r-- | third_party/heimdal/lib/krb5/verify_krb5_conf.c | 795 |
1 files changed, 795 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/krb5/verify_krb5_conf.c b/third_party/heimdal/lib/krb5/verify_krb5_conf.c new file mode 100644 index 0000000..c258a2b --- /dev/null +++ b/third_party/heimdal/lib/krb5/verify_krb5_conf.c @@ -0,0 +1,795 @@ +/* + * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <getarg.h> +#include <parse_bytes.h> +#include <err.h> + +/* verify krb5.conf */ +static int dumpconfig_flag = 0; +static int version_flag = 0; +static int help_flag = 0; +static int warn_mit_syntax_flag = 0; + +static struct getargs args[] = { + {"dumpconfig", 0, arg_flag, &dumpconfig_flag, + "show the parsed config files", NULL }, + {"warn-mit-syntax", 0, arg_flag, &warn_mit_syntax_flag, + "show the parsed config files", NULL }, + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + "[config-file]"); + exit (ret); +} + +static int +check_bytes(krb5_context context, const char *path, char *data) +{ + if(parse_bytes(data, NULL) == -1) { + krb5_warnx(context, "%s: failed to parse \"%s\" as size", path, data); + return 1; + } + return 0; +} + +static int +check_time(krb5_context context, const char *path, char *data) +{ + if(parse_time(data, NULL) == -1) { + krb5_warnx(context, "%s: failed to parse \"%s\" as time", path, data); + return 1; + } + return 0; +} + +static int +check_numeric(krb5_context context, const char *path, char *data) +{ + long v; + char *end; + v = strtol(data, &end, 0); + + if ((v == LONG_MIN || v == LONG_MAX) && errno != 0) { + krb5_warnx(context, "%s: over/under flow for \"%s\"", + path, data); + return 1; + } + if(*end != '\0') { + krb5_warnx(context, "%s: failed to parse \"%s\" as a number", + path, data); + return 1; + } + return 0; +} + +static int +check_boolean(krb5_context context, const char *path, char *data) +{ + long int v; + char *end; + if(strcasecmp(data, "yes") == 0 || + strcasecmp(data, "true") == 0 || + strcasecmp(data, "no") == 0 || + strcasecmp(data, "false") == 0) + return 0; + v = strtol(data, &end, 0); + if(*end != '\0') { + krb5_warnx(context, "%s: failed to parse \"%s\" as a boolean", + path, data); + return 1; + } + if(v != 0 && v != 1) + krb5_warnx(context, "%s: numeric value \"%s\" is treated as \"true\"", + path, data); + return 0; +} + +static int +check_524(krb5_context context, const char *path, char *data) +{ + if(strcasecmp(data, "yes") == 0 || + strcasecmp(data, "no") == 0 || + strcasecmp(data, "2b") == 0 || + strcasecmp(data, "local") == 0) + return 0; + + krb5_warnx(context, "%s: didn't contain a valid option `%s'", + path, data); + return 1; +} + +static int +check_host(krb5_context context, const char *path, char *data) +{ + int ret; + char hostname[128]; + const char *p = data; + struct addrinfo hints; + char service[32]; + int defport; + struct addrinfo *ai; + + hints.ai_flags = 0; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + /* XXX data could be a list of hosts that this code can't handle */ + /* XXX copied from krbhst.c */ + if (strncmp(p, "http://", 7) == 0){ + p += 7; + hints.ai_socktype = SOCK_STREAM; + strlcpy(service, "http", sizeof(service)); + defport = 80; + } else if (strncmp(p, "http/", 5) == 0) { + p += 5; + hints.ai_socktype = SOCK_STREAM; + strlcpy(service, "http", sizeof(service)); + defport = 80; + } else if (strncmp(p, "tcp/", 4) == 0){ + p += 4; + hints.ai_socktype = SOCK_STREAM; + strlcpy(service, "kerberos", sizeof(service)); + defport = 88; + } else if (strncmp(p, "udp/", 4) == 0) { + p += 4; + hints.ai_socktype = SOCK_DGRAM; + strlcpy(service, "kerberos", sizeof(service)); + defport = 88; + } else { + hints.ai_socktype = SOCK_DGRAM; + strlcpy(service, "kerberos", sizeof(service)); + defport = 88; + } + if (strsep_copy(&p, ":", hostname, sizeof(hostname)) < 0) { + return 1; + } + hostname[strcspn(hostname, "/")] = '\0'; + if (p != NULL) { + char *end; + int tmp = strtol(p, &end, 0); + if (end == p) { + krb5_warnx(context, "%s: failed to parse port number in %s", + path, data); + return 1; + } + defport = tmp; + snprintf(service, sizeof(service), "%u", defport); + } + ret = getaddrinfo(hostname, service, &hints, &ai); + if (ret == EAI_SERVICE && !isdigit((unsigned char)service[0])) { + snprintf(service, sizeof(service), "%u", defport); + ret = getaddrinfo(hostname, service, &hints, &ai); + } + if (ret != 0) { + krb5_warnx(context, "%s: %s (%s)", path, gai_strerror(ret), hostname); + return 1; + } + freeaddrinfo(ai); + return 0; +} + +static int +check_directory(krb5_context context, const char *path, char *data) +{ + DIR *d = opendir(data); + if (d == NULL) { + krb5_warn(context, errno, "%s: could not open directory `%s'", + path, data); + return 1; + } + + closedir(d); + return 0; +} + +static int +mit_entry(krb5_context context, const char *path, char *data) +{ + if (warn_mit_syntax_flag) + krb5_warnx(context, "%s is only used by MIT Kerberos", path); + return 0; +} + +struct s2i { + const char *s; + int val; +}; + +#define L(X) { #X, LOG_ ## X } + +static struct s2i syslogvals[] = { + /* severity */ + L(EMERG), + L(ALERT), + L(CRIT), + L(ERR), + L(WARNING), + L(NOTICE), + L(INFO), + L(DEBUG), + /* facility */ + L(AUTH), +#ifdef LOG_AUTHPRIV + L(AUTHPRIV), +#endif +#ifdef LOG_CRON + L(CRON), +#endif + L(DAEMON), +#ifdef LOG_FTP + L(FTP), +#endif + L(KERN), + L(LPR), + L(MAIL), +#ifdef LOG_NEWS + L(NEWS), +#endif + L(SYSLOG), + L(USER), +#ifdef LOG_UUCP + L(UUCP), +#endif + L(LOCAL0), + L(LOCAL1), + L(LOCAL2), + L(LOCAL3), + L(LOCAL4), + L(LOCAL5), + L(LOCAL6), + L(LOCAL7), + { NULL, -1 } +}; + +static int +find_value(const char *s, struct s2i *table) +{ + while (table->s && strcasecmp(table->s, s) != 0) + table++; + return table->val; +} + +static int +check_log(krb5_context context, const char *path, char *data) +{ + /* XXX sync with log.c */ + int min = 0, max = -1, n; + char c; + const char *p = data; +#ifdef _WIN32 + const char *q; +#endif + + n = sscanf(p, "%d%c%d/", &min, &c, &max); + if(n == 2){ + if(ISPATHSEP(c)) { + if(min < 0){ + max = -min; + min = 0; + }else{ + max = min; + } + } + } + if(n){ +#ifdef _WIN32 + q = strrchr(p, '\\'); + if (q != NULL) + p = q; + else +#endif + p = strchr(p, '/'); + if(p == NULL) { + krb5_warnx(context, "%s: failed to parse \"%s\"", path, data); + return 1; + } + p++; + } + if(strcmp(p, "STDERR") == 0 || + strcmp(p, "CONSOLE") == 0 || + (strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')) || + (strncmp(p, "DEVICE", 6) == 0 && p[6] == '=')) + return 0; + if(strncmp(p, "SYSLOG", 6) == 0){ + int ret = 0; + char severity[128] = ""; + char facility[128] = ""; + p += 6; + if(*p != '\0') + p++; + if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1) + strsep_copy(&p, ":", facility, sizeof(facility)); + if(*severity == '\0') + strlcpy(severity, "ERR", sizeof(severity)); + if(*facility == '\0') + strlcpy(facility, "AUTH", sizeof(facility)); + if(find_value(facility, syslogvals) == -1) { + krb5_warnx(context, "%s: unknown syslog facility \"%s\"", + path, facility); + ret++; + } + if(find_value(severity, syslogvals) == -1) { + krb5_warnx(context, "%s: unknown syslog severity \"%s\"", + path, severity); + ret++; + } + return ret; + }else{ + krb5_warnx(context, "%s: unknown log type: \"%s\"", path, data); + return 1; + } +} + +typedef int (*check_func_t)(krb5_context, const char*, char*); +struct entry { + const char *name; + int type; + void *check_data; + int deprecated; +}; + +struct entry all_strings[] = { + { "", krb5_config_string, NULL, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry all_boolean[] = { + { "", krb5_config_string, check_boolean, 0 }, + { NULL, 0, NULL, 0 } +}; + + +struct entry v4_name_convert_entries[] = { + { "host", krb5_config_list, all_strings, 0 }, + { "plain", krb5_config_list, all_strings, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry libdefaults_entries[] = { + { "accept_null_addresses", krb5_config_string, check_boolean, 0 }, + { "allow_weak_crypto", krb5_config_string, check_boolean, 0 }, + { "capath", krb5_config_list, all_strings, 1 }, + { "ccapi_library", krb5_config_string, NULL, 0 }, + { "check_pac", krb5_config_string, check_boolean, 0 }, + { "check-rd-req-server", krb5_config_string, check_boolean, 0 }, + { "clockskew", krb5_config_string, check_time, 0 }, + { "date_format", krb5_config_string, NULL, 0 }, + { "default_as_etypes", krb5_config_string, NULL, 0 }, + { "default_ccache_name", krb5_config_string, NULL, 0 }, + { "default_client_keytab_name", krb5_config_string, NULL, 0 }, + { "default_cc_name", krb5_config_string, NULL, 0 }, + { "default_cc_type", krb5_config_string, NULL, 0 }, + { "default_cc_collection", krb5_config_string, NULL, 0 }, + { "default_etypes", krb5_config_string, NULL, 0 }, + { "default_etypes_des", krb5_config_string, NULL, 0 }, + { "default_keytab_modify_name", krb5_config_string, NULL, 0 }, + { "default_keytab_name", krb5_config_string, NULL, 0 }, + { "default_keytab_modify_name", krb5_config_string, NULL, 0 }, + { "default_realm", krb5_config_string, NULL, 0 }, + { "default_tgs_etypes", krb5_config_string, NULL, 0 }, + { "dns_canonicalize_hostname", krb5_config_string, check_boolean, 0 }, + { "dns_proxy", krb5_config_string, NULL, 0 }, + { "dns_lookup_kdc", krb5_config_string, check_boolean, 0 }, + { "dns_lookup_realm", krb5_config_string, check_boolean, 0 }, + { "dns_lookup_realm_labels", krb5_config_string, NULL, 0 }, + { "egd_socket", krb5_config_string, NULL, 0 }, + { "encrypt", krb5_config_string, check_boolean, 0 }, + { "extra_addresses", krb5_config_string, NULL, 0 }, + { "fcache_version", krb5_config_string, check_numeric, 0 }, + { "fcache_strict_checking", krb5_config_string, check_boolean, 0 }, + { "fcc-mit-ticketflags", krb5_config_string, check_boolean, 0 }, + { "forward", krb5_config_string, check_boolean, 0 }, + { "forwardable", krb5_config_string, check_boolean, 0 }, + { "allow_hierarchical_capaths", krb5_config_string, check_boolean, 0 }, + { "host_timeout", krb5_config_string, check_time, 0 }, + { "http_proxy", krb5_config_string, check_host /* XXX */, 0 }, + { "ignore_addresses", krb5_config_string, NULL, 0 }, + { "k5login_authoritative", krb5_config_string, check_boolean, 0 }, + { "k5login_directory", krb5_config_string, NULL, 0 }, + { "kdc_timeout", krb5_config_string, check_time, 0 }, + { "kdc_timesync", krb5_config_string, check_boolean, 0 }, + { "kuserok", krb5_config_string, NULL, 0 }, + { "large_message_size", krb5_config_string, check_numeric, 0 }, + { "log_utc", krb5_config_string, check_boolean, 0 }, + { "max_retries", krb5_config_string, check_numeric, 0 }, + { "maximum_message_size", krb5_config_string, check_numeric, 0 }, + { "moduli", krb5_config_string, NULL, 0 }, + { "name_canon_rules", krb5_config_string, NULL, 0 }, + { "no-addresses", krb5_config_string, check_boolean, 0 }, + { "pkinit_dh_min_bits", krb5_config_string, NULL, 0 }, + { "plugin_dir", krb5_config_string, check_directory, 0 }, + { "proxiable", krb5_config_string, check_boolean, 0 }, + { "renew_lifetime", krb5_config_string, check_time, 0 }, + { "scan_interfaces", krb5_config_string, check_boolean, 0 }, + { "srv_lookup", krb5_config_string, check_boolean, 0 }, + { "srv_try_txt", krb5_config_string, check_boolean, 0 }, + { "ticket_lifetime", krb5_config_string, check_time, 0 }, + { "time_format", krb5_config_string, NULL, 0 }, + { "transited_realms_reject", krb5_config_string, NULL, 0 }, + { "use_fallback", krb5_config_string, check_boolean, 0 }, + { "v4_instance_resolve", krb5_config_string, check_boolean, 0 }, + { "v4_name_convert", krb5_config_list, v4_name_convert_entries, 0 }, + { "verify_ap_req_nofail", krb5_config_string, check_boolean, 0 }, + { "warn_pwexpire", krb5_config_string, check_time, 0 }, + + /* MIT stuff */ + { "permitted_enctypes", krb5_config_string, mit_entry, 0 }, + { "default_tgs_enctypes", krb5_config_string, mit_entry, 0 }, + { "default_tkt_enctypes", krb5_config_string, mit_entry, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry appdefaults_entries[] = { + { "afslog", krb5_config_string, check_boolean, 0 }, + { "afs-use-524", krb5_config_string, check_524, 0 }, +#if 0 + { "anonymous", krb5_config_string, check_boolean, 0 }, +#endif + { "encrypt", krb5_config_string, check_boolean, 0 }, + { "forward", krb5_config_string, check_boolean, 0 }, + { "forwardable", krb5_config_string, check_boolean, 0 }, + { "krb4_get_tickets", krb5_config_string, check_boolean, 0 }, + { "proxiable", krb5_config_string, check_boolean, 0 }, + { "renew_lifetime", krb5_config_string, check_time, 0 }, + { "no-addresses", krb5_config_string, check_boolean, 0 }, + { "pkinit_anchors", krb5_config_string, NULL, 0 }, + { "pkinit_pool", krb5_config_string, NULL, 0 }, + { "pkinit_require_eku", krb5_config_string, NULL, 0 }, + { "pkinit_require_hostname_match", krb5_config_string, NULL, 0 }, + { "pkinit_require_krbtgt_otherName", krb5_config_string, NULL, 0 }, + { "pkinit_revoke", krb5_config_string, NULL, 0 }, + { "pkinit_trustedCertifiers", krb5_config_string, check_boolean, 0 }, + { "pkinit_win2k", krb5_config_string, NULL, 0 }, + { "pkinit_win2k_require_binding", krb5_config_string, NULL, 0 }, + { "ticket_lifetime", krb5_config_string, check_time, 0 }, + { "", krb5_config_list, appdefaults_entries, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry realms_entries[] = { + { "admin_server", krb5_config_string, check_host, 0 }, + { "auth_to_local", krb5_config_string, NULL, 0 }, + { "auth_to_local_names", krb5_config_string, NULL, 0 }, + { "default_domain", krb5_config_string, NULL, 0 }, + { "forwardable", krb5_config_string, check_boolean, 0 }, + { "allow_hierarchical_capaths", krb5_config_string, check_boolean, 0 }, + { "kdc", krb5_config_string, check_host, 0 }, + { "kpasswd_server", krb5_config_string, check_host, 0 }, + { "krb524_server", krb5_config_string, check_host, 0 }, + { "kx509_ca", krb5_config_string, NULL, 0 }, + { "kx509_include_pkinit_san", krb5_config_string, check_boolean, 0 }, + { "name_canon_rules", krb5_config_string, NULL, 0 }, + { "no-addresses", krb5_config_string, check_boolean, 0 }, + { "pkinit_anchors", krb5_config_string, NULL, 0 }, + { "pkinit_require_eku", krb5_config_string, NULL, 0 }, + { "pkinit_require_hostname_match", krb5_config_string, NULL, 0 }, + { "pkinit_require_krbtgt_otherName", krb5_config_string, NULL, 0 }, + { "pkinit_trustedCertifiers", krb5_config_string, check_boolean, 0 }, + { "pkinit_win2k", krb5_config_string, NULL, 0 }, + { "pkinit_win2k_require_binding", krb5_config_string, NULL, 0 }, + { "proxiable", krb5_config_string, check_boolean, 0 }, + { "renew_lifetime", krb5_config_string, check_time, 0 }, + { "require_initial_kca_tickets", krb5_config_string, check_boolean, 0 }, + { "ticket_lifetime", krb5_config_string, check_time, 0 }, + { "v4_domains", krb5_config_string, NULL, 0 }, + { "v4_instance_convert", krb5_config_list, all_strings, 0 }, + { "v4_name_convert", krb5_config_list, v4_name_convert_entries, 0 }, + { "warn_pwexpire", krb5_config_string, check_time, 0 }, + { "win2k_pkinit", krb5_config_string, NULL, 0 }, + + /* MIT stuff */ + { "admin_keytab", krb5_config_string, mit_entry, 0 }, + { "acl_file", krb5_config_string, mit_entry, 0 }, + { "database_name", krb5_config_string, mit_entry, 0 }, + { "default_principal_expiration", krb5_config_string, mit_entry, 0 }, + { "default_principal_flags", krb5_config_string, mit_entry, 0 }, + { "dict_file", krb5_config_string, mit_entry, 0 }, + { "kadmind_port", krb5_config_string, mit_entry, 0 }, + { "kpasswd_port", krb5_config_string, mit_entry, 0 }, + { "master_kdc", krb5_config_string, mit_entry, 0 }, + { "master_key_name", krb5_config_string, mit_entry, 0 }, + { "master_key_type", krb5_config_string, mit_entry, 0 }, + { "key_stash_file", krb5_config_string, mit_entry, 0 }, + { "max_life", krb5_config_string, mit_entry, 0 }, + { "max_renewable_life", krb5_config_string, mit_entry, 0 }, + { "supported_enctypes", krb5_config_string, mit_entry, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry realms_foobar[] = { + { "", krb5_config_list, realms_entries, 0 }, + { NULL, 0, NULL, 0 } +}; + + +struct entry kdc_database_entries[] = { + { "acl_file", krb5_config_string, NULL, 0 }, + { "dbname", krb5_config_string, NULL, 0 }, + { "log_file", krb5_config_string, NULL, 0 }, + { "mkey_file", krb5_config_string, NULL, 0 }, + { "realm", krb5_config_string, NULL, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry kdc_entries[] = { + { "addresses", krb5_config_string, NULL, 0 }, + { "allow-anonymous", krb5_config_string, check_boolean, 0 }, + { "allow-null-ticket-addresses", krb5_config_string, check_boolean, 0 }, + { "check-ticket-addresses", krb5_config_string, check_boolean, 0 }, + { "database", krb5_config_list, kdc_database_entries, 0 }, + { "detach", krb5_config_string, check_boolean, 0 }, + { "digests_allowed", krb5_config_string, NULL, 0 }, + { "disable-des", krb5_config_string, check_boolean, 0 }, + { "enable-524", krb5_config_string, check_boolean, 0 }, + { "enable-digest", krb5_config_string, check_boolean, 0 }, + { "enable-kaserver", krb5_config_string, check_boolean, 1 }, + { "enable-kerberos4", krb5_config_string, check_boolean, 1 }, + { "enable-kx509", krb5_config_string, check_boolean, 0 }, + { "enable-http", krb5_config_string, check_boolean, 0 }, + { "enable-pkinit", krb5_config_string, check_boolean, 0 }, + { "encode_as_rep_as_tgs_rep", krb5_config_string, check_boolean, 0 }, + { "enforce-transited-policy", krb5_config_string, NULL, 1 }, + { "hdb-ldap-create-base", krb5_config_string, NULL, 0 }, + { "iprop-acl", krb5_config_string, NULL, 0 }, + { "iprop-stats", krb5_config_string, NULL, 0 }, + { "kdc-request-log", krb5_config_string, NULL, 0 }, + { "kdc_warn_pwexpire", krb5_config_string, check_time, 0 }, + { "key-file", krb5_config_string, NULL, 0 }, + { "kx509_ca", krb5_config_string, NULL, 0 }, + { "kx509_include_pkinit_san", krb5_config_string, check_boolean, 0 }, + { "kx509_template", krb5_config_string, NULL, 0 }, + { "logging", krb5_config_string, check_log, 0 }, + { "max-kdc-datagram-reply-length", krb5_config_string, check_bytes, 0 }, + { "max-request", krb5_config_string, check_bytes, 0 }, + { "num-kdc-processes", krb5_config_string, check_numeric, 0 }, + { "pkinit_allow_proxy_certificate", krb5_config_string, check_boolean, 0 }, + { "pkinit_anchors", krb5_config_string, NULL, 0 }, + { "pkinit_dh_min_bits", krb5_config_string, check_numeric, 0 }, + { "pkinit_identity", krb5_config_string, NULL, 0 }, + { "pkinit_kdc_friendly_name", krb5_config_string, NULL, 0 }, + { "pkinit_kdc_ocsp", krb5_config_string, NULL, 0 }, + { "pkinit_mappings_file", krb5_config_string, NULL, 0 }, + { "pkinit_pool", krb5_config_string, NULL, 0 }, + { "pkinit_principal_in_certificate", krb5_config_string, check_boolean, 0 }, + { "pkinit_revoke", krb5_config_string, NULL, 0 }, + { "pkinit_win2k_require_binding", krb5_config_string, check_boolean, 0 }, + { "ports", krb5_config_string, NULL, 0 }, + { "preauth-use-strongest-session-key", krb5_config_string, check_boolean, 0 }, + { "require_initial_kca_tickets", krb5_config_string, check_boolean, 0 }, + { "require-preauth", krb5_config_string, check_boolean, 0 }, + { "strict-nametypes", krb5_config_string, check_boolean, 0 }, + { "svc-use-strongest-session-key", krb5_config_string, check_boolean, 0 }, + { "tgt-use-strongest-session-key", krb5_config_string, check_boolean, 0 }, + { "transited-policy", krb5_config_string, NULL, 0 }, + { "use_2b", krb5_config_list, NULL, 0 }, + { "use-strongest-server-key", krb5_config_string, check_boolean, 0 }, + { "v4_realm", krb5_config_string, NULL, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry kadmin_entries[] = { + { "allow_self_change_password", krb5_config_string, check_boolean, 0 }, + { "default_keys", krb5_config_string, NULL, 0 }, + { "password_lifetime", krb5_config_string, check_time, 0 }, + { "plugin_dir", krb5_config_string, check_directory, 0 }, + { "require-preauth", krb5_config_string, check_boolean, 0 }, + { "save-password", krb5_config_string, check_boolean, 0 }, + { "use_v4_salt", krb5_config_string, NULL, 0 }, + { NULL, 0, NULL, 0 } +}; +struct entry log_strings[] = { + { "", krb5_config_string, check_log, 0 }, + { NULL, 0, NULL, 0 } +}; + + +/* MIT stuff */ +struct entry kdcdefaults_entries[] = { + { "kdc_ports", krb5_config_string, mit_entry, 0 }, + { "v4_mode", krb5_config_string, mit_entry, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry capaths_entries[] = { + { "", krb5_config_list, all_strings, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry kcm_entries[] = { + { "detach", krb5_config_string, check_boolean, 0 }, + { "disallow-getting-krbtgt", krb5_config_string, check_boolean, 0 }, + { "logging", krb5_config_string, NULL, 0 }, + { "max-request", krb5_config_string, NULL, 0 }, + { "system_ccache", krb5_config_string, NULL, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry password_quality_entries[] = { + { "enforce_on_admin_set", krb5_config_string, check_boolean, 0 }, + { "check_function", krb5_config_string, NULL, 0 }, + { "check_library", krb5_config_string, NULL, 0 }, + { "external_program", krb5_config_string, NULL, 0 }, + { "min_classes", krb5_config_string, check_numeric, 0 }, + { "min_length", krb5_config_string, check_numeric, 0 }, + { "policies", krb5_config_string, NULL, 0 }, + { "policy_libraries", krb5_config_string, NULL, 0 }, + { "", krb5_config_list, all_strings, 0 }, + { NULL, 0, NULL, 0 } +}; + +struct entry toplevel_sections[] = { + { "appdefaults", krb5_config_list, appdefaults_entries, 0 }, + { "capaths", krb5_config_list, capaths_entries, 0 }, + { "domain_realm", krb5_config_list, all_strings, 0 }, + { "gssapi", krb5_config_list, NULL, 0 }, + { "kadmin", krb5_config_list, kadmin_entries, 0 }, + { "kcm", krb5_config_list, kcm_entries, 0 }, + { "kdc", krb5_config_list, kdc_entries, 0 }, + { "libdefaults" , krb5_config_list, libdefaults_entries, 0 }, + { "logging", krb5_config_list, log_strings, 0 }, + { "password_quality", krb5_config_list, password_quality_entries, 0 }, + { "realms", krb5_config_list, realms_foobar, 0 }, + + /* MIT stuff */ + { "kdcdefaults", krb5_config_list, kdcdefaults_entries, 0 }, + { NULL, 0, NULL, 0 } +}; + + +static int +check_section(krb5_context context, const char *path, krb5_config_section *cf, + struct entry *entries) +{ + int error = 0; + krb5_config_section *p; + struct entry *e; + + char *local; + + for(p = cf; p != NULL; p = p->next) { + local = NULL; + if (asprintf(&local, "%s/%s", path, p->name) < 0 || local == NULL) + errx(1, "out of memory"); + for(e = entries; e->name != NULL; e++) { + if(*e->name == '\0' || strcmp(e->name, p->name) == 0) { + if(e->type != p->type) { + krb5_warnx(context, "%s: unknown or wrong type", local); + error |= 1; + } else if(p->type == krb5_config_string && e->check_data != NULL) { + error |= (*(check_func_t)e->check_data)(context, local, p->u.string); + } else if(p->type == krb5_config_list && e->check_data != NULL) { + error |= check_section(context, local, p->u.list, e->check_data); + } + if(e->deprecated) { + krb5_warnx(context, "%s: is a deprecated entry", local); + error |= 1; + } + break; + } + } + if(e->name == NULL) { + krb5_warnx(context, "%s: unknown entry", local); + error |= 1; + } + free(local); + } + return error; +} + + +static void +dumpconfig(int level, krb5_config_section *top) +{ + krb5_config_section *x; + for(x = top; x; x = x->next) { + switch(x->type) { + case krb5_config_list: + if(level == 0) { + printf("[%s]\n", x->name); + } else { + printf("%*s%s = {\n", 4 * level, " ", x->name); + } + dumpconfig(level + 1, x->u.list); + if(level > 0) + printf("%*s}\n", 4 * level, " "); + break; + case krb5_config_string: + printf("%*s%s = %s\n", 4 * level, " ", x->name, x->u.string); + break; + } + } +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + krb5_config_section *tmp_cf; + int optidx = 0; + + setprogname (argv[0]); + + ret = krb5_init_context(&context); + if (ret == KRB5_CONFIG_BADFORMAT) + errx (1, "krb5_init_context failed to parse configuration file"); + else if (ret) + errx (1, "krb5_init_context failed with %d", ret); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + tmp_cf = NULL; + if(argc == 0) + krb5_get_default_config_files(&argv); + + while(*argv) { + ret = krb5_config_parse_file_multi(context, *argv, &tmp_cf); + if (ret != 0) + krb5_warn (context, ret, "krb5_config_parse_file"); + argv++; + } + + if(dumpconfig_flag) + dumpconfig(0, tmp_cf); + + return check_section(context, "", tmp_cf, toplevel_sections); +} |