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