do some checks of the values in the file

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10605 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Johan Danielsson
2001-08-30 18:57:39 +00:00
parent b3b7b140cc
commit fd07afcd82
2 changed files with 303 additions and 13 deletions

View File

@@ -1,13 +1,11 @@
.\" $Id$
.\"
.Dd March 4, 2000
.Dd August 30, 2001
.Dt VERIFY_KRB5_CONF 8
.Os HEIMDAL
.Sh NAME
.Nm verify_krb5_conf
.Nd does a crude test that
.Pa krb5.conf
does not contain any obvious syntax error
.Nd checks krb5.conf for obvious errors
.Sh SYNOPSIS
.Nm
.Ar [config-file]
@@ -17,9 +15,34 @@ reads the configuration file
.Pa krb5.conf ,
or the file given on the command line,
and parses it, thereby verifying that the syntax is not correctly wrong.
Since that file is read by almost all Kerberos programs but most of
them have no way of notifying the user that it could not be parsed,
this program is useful.
.Pp
If the file is syntactically correct,
.Nm
tries to verify that the contents of the file is of relevant nature.
.Sh DIAGNOSTICS
Possible output from
.Nm
include:
.Bl -tag -width "<path>"
.It "<path>: failed to parse <something> as size/time/number/boolean"
Usually means that <something> is misspelled, or that it contains
weird characters. The parsing done by
.Nm
is more strict than the one performed by libkrb5, and so strings that
work in real life, might be reported as bad.
.It "<path>: host not found (<hostname>)"
Means that <path> is supposed to point to a host, but it can't be
recognised as one.
.It <path>: unknown or wrong type
Means that <path> is either is a string when it should be a list, vice
versa, or just that
.Nm
is confused.
.It <path>: unknown entry
Means that <string> is not known by
.Nm "" .
.El
.Sh ENVIRONMENT
.Ev KRB5_CONFIG
points to the configuration file to read.
@@ -28,5 +51,12 @@ points to the configuration file to read.
.Sh SEE ALSO
.Xr krb5.conf 5
.Sh BUGS
It should know about what variables are actually used and warn about
unknown ones.
Since each application can put almost anything in the config file,
it's hard to come up with a water tight verification process. Most of
the default settings are sanity checked, but this does not mean that
every problem is discovered, or that everything that is reported as a
possible problem actually is one. This tool should thus be used with
some care.
.Pp
It should warn about obsolete data, or bad practice, but currently
doesn't.

View File

@@ -33,6 +33,7 @@
#include "krb5_locl.h"
#include <getarg.h>
#include <parse_bytes.h>
RCSID("$Id$");
/* verify krb5.conf */
@@ -57,6 +58,263 @@ usage (int ret)
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 int v;
char *end;
v = strtol(data, &end, 0);
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;
}
return 0;
}
static int
check_host(krb5_context context, const char *path, char *data)
{
int ret;
char hostname[128];
const char *p = data;
struct addrinfo *ai;
/* 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;
} else if(strncmp(p, "http/", 5) == 0) {
p += 5;
}else if(strncmp(p, "tcp/", 4) == 0){
p += 4;
} else if(strncmp(p, "udp/", 4) == 0) {
p += 4;
}
if(strsep_copy(&p, ":", hostname, sizeof(hostname)) < 0) {
return 1;
}
hostname[strcspn(hostname, "/")] = '\0';
ret = getaddrinfo(hostname, "telnet" /* XXX */, NULL, &ai);
if(ret != 0) {
if(ret == EAI_NODATA)
krb5_warnx(context, "%s: host not found (%s)", path, hostname);
else
krb5_warnx(context, "%s: %s (%s)", path, gai_strerror(ret), hostname);
return 1;
}
return 0;
}
typedef int (*check_func_t)(krb5_context, const char*, char*);
struct entry {
const char *name;
int type;
void *check_data;
};
struct entry all_strings[] = {
{ "", krb5_config_string, NULL },
{ NULL }
};
struct entry v4_name_convert_entries[] = {
{ "host", krb5_config_list, all_strings },
{ "plain", krb5_config_list, all_strings },
{ NULL }
};
struct entry libdefaults_entries[] = {
{ "accept_null_addresses", krb5_config_string, check_boolean },
{ "capath", krb5_config_list, all_strings },
{ "clockskew", krb5_config_string, check_time },
{ "date_format", krb5_config_string, NULL },
{ "default_etypes", krb5_config_string, NULL },
{ "default_etypes_des", krb5_config_string, NULL },
{ "default_keytab_modify_name", krb5_config_string, NULL },
{ "default_keytab_name", krb5_config_string, NULL },
{ "default_realm", krb5_config_string, NULL },
{ "dns_proxy", krb5_config_string, NULL },
{ "egd_socket", krb5_config_string, NULL },
{ "encrypt", krb5_config_string, check_boolean },
{ "extra_addresses", krb5_config_string, NULL },
{ "fcache_version", krb5_config_string, check_numeric },
{ "forward", krb5_config_string, check_boolean },
{ "forwardable", krb5_config_string, check_boolean },
{ "http_proxy", krb5_config_string, check_host /* XXX */ },
{ "ignore_addresses", krb5_config_string, NULL },
{ "kdc_timeout", krb5_config_string, check_time },
{ "kdc_timesync", krb5_config_string, check_boolean },
{ "krb4_get_tickets", krb5_config_string, check_boolean },
{ "log_utc", krb5_config_string, check_boolean },
{ "maxretries", krb5_config_string, check_numeric },
{ "scan_interfaces", krb5_config_string, check_boolean },
{ "srv_lookup", krb5_config_string, check_boolean },
{ "srv_try_txt", krb5_config_string, check_boolean },
{ "ticket_lifetime", krb5_config_string, check_time },
{ "time_format", krb5_config_string, NULL },
{ "transited_realms_reject", krb5_config_string, NULL },
{ "v4_instance_resolve", krb5_config_string, check_boolean },
{ "v4_name_convert", krb5_config_list, v4_name_convert_entries },
{ "verify_ap_req_nofail", krb5_config_string, check_boolean },
{ NULL }
};
struct entry appdefaults_entries[] = {
{ "forwardable", krb5_config_string, check_boolean },
{ "proxiable", krb5_config_string, check_boolean },
{ "ticket_lifetime", krb5_config_string, check_time },
{ "renew_lifetime", krb5_config_string, check_time },
{ "no-addresses", krb5_config_string, check_boolean },
#if 0
{ "anonymous", krb5_config_string, check_boolean },
#endif
{ "", krb5_config_list, appdefaults_entries },
{ NULL }
};
struct entry realms_entries[] = {
{ "forwardable", krb5_config_string, check_boolean },
{ "proxiable", krb5_config_string, check_boolean },
{ "ticket_lifetime", krb5_config_string, check_time },
{ "renew_lifetime", krb5_config_string, check_time },
{ "warn_pwexpire", krb5_config_string, check_time },
{ "kdc", krb5_config_string, check_host },
{ "admin_server", krb5_config_string, check_host },
{ "kpasswd_server", krb5_config_string, check_host },
{ "krb524_server", krb5_config_string, check_host },
{ "v4_name_convert", krb5_config_list, v4_name_convert_entries },
{ "v4_instance_convert", krb5_config_list, all_strings },
{ "v4_domains", krb5_config_string, NULL },
{ "default_domain", krb5_config_string, NULL },
{ NULL }
};
struct entry realms_foobar[] = {
{ "", krb5_config_list, realms_entries },
{ NULL }
};
struct entry kdc_database_entries[] = {
{ "realm", krb5_config_string, NULL },
{ "dbname", krb5_config_string, NULL },
{ "mkey_file", krb5_config_string, NULL },
{ NULL }
};
struct entry kdc_entries[] = {
{ "database", krb5_config_list, kdc_database_entries },
{ "key-file", krb5_config_string, NULL },
{ "logging", krb5_config_string, NULL },
{ "max-request", krb5_config_string, check_bytes },
{ "require-preauth", krb5_config_string, check_boolean },
{ "ports", krb5_config_string, NULL },
{ "addresses", krb5_config_string, NULL },
{ "enable-kerberos4", krb5_config_string, check_boolean },
{ "enable-524", krb5_config_string, check_boolean },
{ "enable-http", krb5_config_string, check_boolean },
{ "check_ticket-addresses", krb5_config_string, check_boolean },
{ "allow-null-addresses", krb5_config_string, check_boolean },
{ "allow-anonymous", krb5_config_string, check_boolean },
{ "v4_realm", krb5_config_string, NULL },
{ "enable-kaserver", krb5_config_string, check_boolean },
{ "encode_as_rep_as_tgs_rep", krb5_config_string, check_boolean },
{ "kdc_warn_pwexpire", krb5_config_string, check_time },
{ NULL }
};
struct entry kadmin_entries[] = {
{ "password_lifetime", krb5_config_string, check_time },
{ "default_keys", krb5_config_string, NULL },
{ "use_v4_salt", krb5_config_string, NULL },
{ NULL }
};
struct entry toplevel_sections[] = {
{ "libdefaults" , krb5_config_list, libdefaults_entries },
{ "realms", krb5_config_list, realms_foobar },
{ "domain_realm", krb5_config_list, all_strings },
{ "logging", krb5_config_list, all_strings },
{ "kdc", krb5_config_list, kdc_entries },
{ "kadmin", krb5_config_list, kadmin_entries },
{ "appdefaults", krb5_config_list, appdefaults_entries },
{ NULL }
};
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) {
asprintf(&local, "%s/%s", path, p->name);
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);
}
break;
}
}
if(e->name == NULL) {
krb5_warnx(context, "%s: unknown entry", local);
error |= 1;
}
free(local);
}
return error;
}
int
main(int argc, char **argv)
{
@@ -97,8 +355,10 @@ main(int argc, char **argv)
}
ret = krb5_config_parse_file (context, config_file, &tmp_cf);
if (ret == 0)
return 0;
krb5_warn (context, ret, "krb5_config_parse_file");
return 1;
if (ret != 0) {
krb5_warn (context, ret, "krb5_config_parse_file");
return 1;
}
return check_section(context, "", tmp_cf, toplevel_sections);
}