155682Smarkm/*
2233294Sstas * Copyright (c) 1999 - 2005 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "krb5_locl.h"
3555682Smarkm#include <getarg.h>
3690926Snectar#include <parse_bytes.h>
3790926Snectar#include <err.h>
3855682Smarkm
3955682Smarkm/* verify krb5.conf */
4055682Smarkm
41102644Snectarstatic int dumpconfig_flag = 0;
4255682Smarkmstatic int version_flag = 0;
4355682Smarkmstatic int help_flag	= 0;
44178825Sdfrstatic int warn_mit_syntax_flag = 0;
4555682Smarkm
4655682Smarkmstatic struct getargs args[] = {
47233294Sstas    {"dumpconfig", 0,      arg_flag,       &dumpconfig_flag,
48102644Snectar     "show the parsed config files", NULL },
49233294Sstas    {"warn-mit-syntax", 0, arg_flag,       &warn_mit_syntax_flag,
50178825Sdfr     "show the parsed config files", NULL },
5155682Smarkm    {"version",	0,	arg_flag,	&version_flag,
5255682Smarkm     "print version", NULL },
5355682Smarkm    {"help",	0,	arg_flag,	&help_flag,
5455682Smarkm     NULL, NULL }
5555682Smarkm};
5655682Smarkm
5755682Smarkmstatic void
5855682Smarkmusage (int ret)
5955682Smarkm{
6055682Smarkm    arg_printusage (args,
6155682Smarkm		    sizeof(args)/sizeof(*args),
6255682Smarkm		    NULL,
6355682Smarkm		    "[config-file]");
6455682Smarkm    exit (ret);
6555682Smarkm}
6655682Smarkm
6790926Snectarstatic int
6890926Snectarcheck_bytes(krb5_context context, const char *path, char *data)
6990926Snectar{
7090926Snectar    if(parse_bytes(data, NULL) == -1) {
7190926Snectar	krb5_warnx(context, "%s: failed to parse \"%s\" as size", path, data);
7290926Snectar	return 1;
7390926Snectar    }
7490926Snectar    return 0;
7590926Snectar}
7690926Snectar
7790926Snectarstatic int
7890926Snectarcheck_time(krb5_context context, const char *path, char *data)
7990926Snectar{
8090926Snectar    if(parse_time(data, NULL) == -1) {
8190926Snectar	krb5_warnx(context, "%s: failed to parse \"%s\" as time", path, data);
8290926Snectar	return 1;
8390926Snectar    }
8490926Snectar    return 0;
8590926Snectar}
8690926Snectar
8790926Snectarstatic int
8890926Snectarcheck_numeric(krb5_context context, const char *path, char *data)
8990926Snectar{
90233294Sstas    long v;
9190926Snectar    char *end;
9290926Snectar    v = strtol(data, &end, 0);
93233294Sstas
94233294Sstas    if ((v == LONG_MIN || v == LONG_MAX) && errno != 0) {
95233294Sstas	krb5_warnx(context, "%s: over/under flow for \"%s\"",
96233294Sstas		   path, data);
97233294Sstas	return 1;
98233294Sstas    }
9990926Snectar    if(*end != '\0') {
100233294Sstas	krb5_warnx(context, "%s: failed to parse \"%s\" as a number",
10190926Snectar		   path, data);
10290926Snectar	return 1;
10390926Snectar    }
10490926Snectar    return 0;
10590926Snectar}
10690926Snectar
10790926Snectarstatic int
10890926Snectarcheck_boolean(krb5_context context, const char *path, char *data)
10990926Snectar{
11090926Snectar    long int v;
11190926Snectar    char *end;
11290926Snectar    if(strcasecmp(data, "yes") == 0 ||
11390926Snectar       strcasecmp(data, "true") == 0 ||
11490926Snectar       strcasecmp(data, "no") == 0 ||
11590926Snectar       strcasecmp(data, "false") == 0)
11690926Snectar	return 0;
11790926Snectar    v = strtol(data, &end, 0);
11890926Snectar    if(*end != '\0') {
119233294Sstas	krb5_warnx(context, "%s: failed to parse \"%s\" as a boolean",
12090926Snectar		   path, data);
12190926Snectar	return 1;
12290926Snectar    }
123102644Snectar    if(v != 0 && v != 1)
124233294Sstas	krb5_warnx(context, "%s: numeric value \"%s\" is treated as \"true\"",
125102644Snectar		   path, data);
12690926Snectar    return 0;
12790926Snectar}
12890926Snectar
12990926Snectarstatic int
130120945Snectarcheck_524(krb5_context context, const char *path, char *data)
131120945Snectar{
132120945Snectar    if(strcasecmp(data, "yes") == 0 ||
133120945Snectar       strcasecmp(data, "no") == 0 ||
134120945Snectar       strcasecmp(data, "2b") == 0 ||
135120945Snectar       strcasecmp(data, "local") == 0)
136120945Snectar	return 0;
137120945Snectar
138233294Sstas    krb5_warnx(context, "%s: didn't contain a valid option `%s'",
139120945Snectar	       path, data);
140120945Snectar    return 1;
141120945Snectar}
142120945Snectar
143120945Snectarstatic int
14490926Snectarcheck_host(krb5_context context, const char *path, char *data)
14590926Snectar{
14690926Snectar    int ret;
14790926Snectar    char hostname[128];
14890926Snectar    const char *p = data;
149178825Sdfr    struct addrinfo hints;
150178825Sdfr    char service[32];
151178825Sdfr    int defport;
15290926Snectar    struct addrinfo *ai;
153178825Sdfr
154178825Sdfr    hints.ai_flags = 0;
155178825Sdfr    hints.ai_family = PF_UNSPEC;
156178825Sdfr    hints.ai_socktype = 0;
157178825Sdfr    hints.ai_protocol = 0;
158178825Sdfr
159178825Sdfr    hints.ai_addrlen = 0;
160178825Sdfr    hints.ai_canonname = NULL;
161178825Sdfr    hints.ai_addr = NULL;
162178825Sdfr    hints.ai_next = NULL;
163233294Sstas
16490926Snectar    /* XXX data could be a list of hosts that this code can't handle */
16590926Snectar    /* XXX copied from krbhst.c */
16690926Snectar    if(strncmp(p, "http://", 7) == 0){
16790926Snectar        p += 7;
168178825Sdfr	hints.ai_socktype = SOCK_STREAM;
169178825Sdfr	strlcpy(service, "http", sizeof(service));
170178825Sdfr	defport = 80;
17190926Snectar    } else if(strncmp(p, "http/", 5) == 0) {
17290926Snectar        p += 5;
173178825Sdfr	hints.ai_socktype = SOCK_STREAM;
174178825Sdfr	strlcpy(service, "http", sizeof(service));
175178825Sdfr	defport = 80;
17690926Snectar    }else if(strncmp(p, "tcp/", 4) == 0){
17790926Snectar        p += 4;
178178825Sdfr	hints.ai_socktype = SOCK_STREAM;
179178825Sdfr	strlcpy(service, "kerberos", sizeof(service));
180178825Sdfr	defport = 88;
18190926Snectar    } else if(strncmp(p, "udp/", 4) == 0) {
18290926Snectar        p += 4;
183178825Sdfr	hints.ai_socktype = SOCK_DGRAM;
184178825Sdfr	strlcpy(service, "kerberos", sizeof(service));
185178825Sdfr	defport = 88;
186178825Sdfr    } else {
187178825Sdfr	hints.ai_socktype = SOCK_DGRAM;
188178825Sdfr	strlcpy(service, "kerberos", sizeof(service));
189178825Sdfr	defport = 88;
19090926Snectar    }
19190926Snectar    if(strsep_copy(&p, ":", hostname, sizeof(hostname)) < 0) {
19290926Snectar	return 1;
19390926Snectar    }
19490926Snectar    hostname[strcspn(hostname, "/")] = '\0';
195178825Sdfr    if(p != NULL) {
196178825Sdfr	char *end;
197178825Sdfr	int tmp = strtol(p, &end, 0);
198178825Sdfr	if(end == p) {
199233294Sstas	    krb5_warnx(context, "%s: failed to parse port number in %s",
200178825Sdfr		       path, data);
201178825Sdfr	    return 1;
202178825Sdfr	}
203178825Sdfr	defport = tmp;
204178825Sdfr	snprintf(service, sizeof(service), "%u", defport);
205178825Sdfr    }
206178825Sdfr    ret = getaddrinfo(hostname, service, &hints, &ai);
207178825Sdfr    if(ret == EAI_SERVICE && !isdigit((unsigned char)service[0])) {
208178825Sdfr	snprintf(service, sizeof(service), "%u", defport);
209178825Sdfr	ret = getaddrinfo(hostname, service, &hints, &ai);
210178825Sdfr    }
21190926Snectar    if(ret != 0) {
212127808Snectar	krb5_warnx(context, "%s: %s (%s)", path, gai_strerror(ret), hostname);
21390926Snectar	return 1;
21490926Snectar    }
21590926Snectar    return 0;
21690926Snectar}
21790926Snectar
218102644Snectarstatic int
219102644Snectarmit_entry(krb5_context context, const char *path, char *data)
220102644Snectar{
221178825Sdfr    if (warn_mit_syntax_flag)
222178825Sdfr	krb5_warnx(context, "%s is only used by MIT Kerberos", path);
223102644Snectar    return 0;
224102644Snectar}
225102644Snectar
226102644Snectarstruct s2i {
227178825Sdfr    const char *s;
228102644Snectar    int val;
229102644Snectar};
230102644Snectar
231102644Snectar#define L(X) { #X, LOG_ ## X }
232102644Snectar
233102644Snectarstatic struct s2i syslogvals[] = {
234120945Snectar    /* severity */
235102644Snectar    L(EMERG),
236102644Snectar    L(ALERT),
237102644Snectar    L(CRIT),
238102644Snectar    L(ERR),
239102644Snectar    L(WARNING),
240102644Snectar    L(NOTICE),
241102644Snectar    L(INFO),
242102644Snectar    L(DEBUG),
243120945Snectar    /* facility */
244102644Snectar    L(AUTH),
245102644Snectar#ifdef LOG_AUTHPRIV
246102644Snectar    L(AUTHPRIV),
247102644Snectar#endif
248102644Snectar#ifdef LOG_CRON
249102644Snectar    L(CRON),
250102644Snectar#endif
251102644Snectar    L(DAEMON),
252102644Snectar#ifdef LOG_FTP
253102644Snectar    L(FTP),
254102644Snectar#endif
255102644Snectar    L(KERN),
256102644Snectar    L(LPR),
257102644Snectar    L(MAIL),
258102644Snectar#ifdef LOG_NEWS
259102644Snectar    L(NEWS),
260102644Snectar#endif
261102644Snectar    L(SYSLOG),
262102644Snectar    L(USER),
263102644Snectar#ifdef LOG_UUCP
264102644Snectar    L(UUCP),
265102644Snectar#endif
266102644Snectar    L(LOCAL0),
267102644Snectar    L(LOCAL1),
268102644Snectar    L(LOCAL2),
269102644Snectar    L(LOCAL3),
270102644Snectar    L(LOCAL4),
271102644Snectar    L(LOCAL5),
272102644Snectar    L(LOCAL6),
273102644Snectar    L(LOCAL7),
274102644Snectar    { NULL, -1 }
275102644Snectar};
276102644Snectar
277102644Snectarstatic int
278102644Snectarfind_value(const char *s, struct s2i *table)
279102644Snectar{
280102644Snectar    while(table->s && strcasecmp(table->s, s))
281102644Snectar	table++;
282102644Snectar    return table->val;
283102644Snectar}
284102644Snectar
285102644Snectarstatic int
286102644Snectarcheck_log(krb5_context context, const char *path, char *data)
287102644Snectar{
288102644Snectar    /* XXX sync with log.c */
289102644Snectar    int min = 0, max = -1, n;
290102644Snectar    char c;
291102644Snectar    const char *p = data;
292102644Snectar
293102644Snectar    n = sscanf(p, "%d%c%d/", &min, &c, &max);
294102644Snectar    if(n == 2){
295102644Snectar	if(c == '/') {
296102644Snectar	    if(min < 0){
297102644Snectar		max = -min;
298102644Snectar		min = 0;
299102644Snectar	    }else{
300102644Snectar		max = min;
301102644Snectar	    }
302102644Snectar	}
303102644Snectar    }
304102644Snectar    if(n){
305102644Snectar	p = strchr(p, '/');
306102644Snectar	if(p == NULL) {
307102644Snectar	    krb5_warnx(context, "%s: failed to parse \"%s\"", path, data);
308102644Snectar	    return 1;
309102644Snectar	}
310102644Snectar	p++;
311102644Snectar    }
312233294Sstas    if(strcmp(p, "STDERR") == 0 ||
313102644Snectar       strcmp(p, "CONSOLE") == 0 ||
314102644Snectar       (strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')) ||
315102644Snectar       (strncmp(p, "DEVICE", 6) == 0 && p[6] == '='))
316102644Snectar	return 0;
317102644Snectar    if(strncmp(p, "SYSLOG", 6) == 0){
318102644Snectar	int ret = 0;
319102644Snectar	char severity[128] = "";
320102644Snectar	char facility[128] = "";
321102644Snectar	p += 6;
322102644Snectar	if(*p != '\0')
323102644Snectar	    p++;
324102644Snectar	if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1)
325102644Snectar	    strsep_copy(&p, ":", facility, sizeof(facility));
326102644Snectar	if(*severity == '\0')
327102644Snectar	    strlcpy(severity, "ERR", sizeof(severity));
328102644Snectar 	if(*facility == '\0')
329102644Snectar	    strlcpy(facility, "AUTH", sizeof(facility));
330120945Snectar	if(find_value(severity, syslogvals) == -1) {
331233294Sstas	    krb5_warnx(context, "%s: unknown syslog facility \"%s\"",
332102644Snectar		       path, facility);
333102644Snectar	    ret++;
334102644Snectar	}
335120945Snectar	if(find_value(severity, syslogvals) == -1) {
336233294Sstas	    krb5_warnx(context, "%s: unknown syslog severity \"%s\"",
337102644Snectar		       path, severity);
338102644Snectar	    ret++;
339102644Snectar	}
340102644Snectar	return ret;
341102644Snectar    }else{
342102644Snectar	krb5_warnx(context, "%s: unknown log type: \"%s\"", path, data);
343102644Snectar	return 1;
344102644Snectar    }
345102644Snectar}
346102644Snectar
34790926Snectartypedef int (*check_func_t)(krb5_context, const char*, char*);
34890926Snectarstruct entry {
34990926Snectar    const char *name;
35090926Snectar    int type;
35190926Snectar    void *check_data;
352233294Sstas    int deprecated;
35390926Snectar};
35490926Snectar
35590926Snectarstruct entry all_strings[] = {
35690926Snectar    { "", krb5_config_string, NULL },
35790926Snectar    { NULL }
35890926Snectar};
35990926Snectar
360178825Sdfrstruct entry all_boolean[] = {
361178825Sdfr    { "", krb5_config_string, check_boolean },
362178825Sdfr    { NULL }
363178825Sdfr};
364178825Sdfr
365178825Sdfr
36690926Snectarstruct entry v4_name_convert_entries[] = {
36790926Snectar    { "host", krb5_config_list, all_strings },
36890926Snectar    { "plain", krb5_config_list, all_strings },
36990926Snectar    { NULL }
37090926Snectar};
37190926Snectar
37290926Snectarstruct entry libdefaults_entries[] = {
37390926Snectar    { "accept_null_addresses", krb5_config_string, check_boolean },
374233294Sstas    { "allow_weak_crypto", krb5_config_string, check_boolean },
375233294Sstas    { "capath", krb5_config_list, all_strings, 1 },
376178825Sdfr    { "check_pac", krb5_config_string, check_boolean },
37790926Snectar    { "clockskew", krb5_config_string, check_time },
37890926Snectar    { "date_format", krb5_config_string, NULL },
379178825Sdfr    { "default_cc_name", krb5_config_string, NULL },
38090926Snectar    { "default_etypes", krb5_config_string, NULL },
38190926Snectar    { "default_etypes_des", krb5_config_string, NULL },
38290926Snectar    { "default_keytab_modify_name", krb5_config_string, NULL },
38390926Snectar    { "default_keytab_name", krb5_config_string, NULL },
38490926Snectar    { "default_realm", krb5_config_string, NULL },
385178825Sdfr    { "dns_canonize_hostname", krb5_config_string, check_boolean },
38690926Snectar    { "dns_proxy", krb5_config_string, NULL },
387102644Snectar    { "dns_lookup_kdc", krb5_config_string, check_boolean },
388102644Snectar    { "dns_lookup_realm", krb5_config_string, check_boolean },
389102644Snectar    { "dns_lookup_realm_labels", krb5_config_string, NULL },
39090926Snectar    { "egd_socket", krb5_config_string, NULL },
39190926Snectar    { "encrypt", krb5_config_string, check_boolean },
39290926Snectar    { "extra_addresses", krb5_config_string, NULL },
39390926Snectar    { "fcache_version", krb5_config_string, check_numeric },
394178825Sdfr    { "fcc-mit-ticketflags", krb5_config_string, check_boolean },
39590926Snectar    { "forward", krb5_config_string, check_boolean },
39690926Snectar    { "forwardable", krb5_config_string, check_boolean },
39790926Snectar    { "http_proxy", krb5_config_string, check_host /* XXX */ },
39890926Snectar    { "ignore_addresses", krb5_config_string, NULL },
39990926Snectar    { "kdc_timeout", krb5_config_string, check_time },
40090926Snectar    { "kdc_timesync", krb5_config_string, check_boolean },
40190926Snectar    { "log_utc", krb5_config_string, check_boolean },
40290926Snectar    { "maxretries", krb5_config_string, check_numeric },
40390926Snectar    { "scan_interfaces", krb5_config_string, check_boolean },
40490926Snectar    { "srv_lookup", krb5_config_string, check_boolean },
405233294Sstas    { "srv_try_txt", krb5_config_string, check_boolean },
40690926Snectar    { "ticket_lifetime", krb5_config_string, check_time },
40790926Snectar    { "time_format", krb5_config_string, NULL },
40890926Snectar    { "transited_realms_reject", krb5_config_string, NULL },
409178825Sdfr    { "no-addresses", krb5_config_string, check_boolean },
41090926Snectar    { "v4_instance_resolve", krb5_config_string, check_boolean },
41190926Snectar    { "v4_name_convert", krb5_config_list, v4_name_convert_entries },
41290926Snectar    { "verify_ap_req_nofail", krb5_config_string, check_boolean },
413178825Sdfr    { "max_retries", krb5_config_string, check_time },
414178825Sdfr    { "renew_lifetime", krb5_config_string, check_time },
415178825Sdfr    { "proxiable", krb5_config_string, check_boolean },
416178825Sdfr    { "warn_pwexpire", krb5_config_string, check_time },
417178825Sdfr    /* MIT stuff */
418178825Sdfr    { "permitted_enctypes", krb5_config_string, mit_entry },
419178825Sdfr    { "default_tgs_enctypes", krb5_config_string, mit_entry },
420178825Sdfr    { "default_tkt_enctypes", krb5_config_string, mit_entry },
42190926Snectar    { NULL }
42290926Snectar};
42390926Snectar
42490926Snectarstruct entry appdefaults_entries[] = {
425120945Snectar    { "afslog", krb5_config_string, check_boolean },
426120945Snectar    { "afs-use-524", krb5_config_string, check_524 },
427178825Sdfr    { "encrypt", krb5_config_string, check_boolean },
428178825Sdfr    { "forward", krb5_config_string, check_boolean },
42990926Snectar    { "forwardable", krb5_config_string, check_boolean },
43090926Snectar    { "proxiable", krb5_config_string, check_boolean },
43190926Snectar    { "ticket_lifetime", krb5_config_string, check_time },
43290926Snectar    { "renew_lifetime", krb5_config_string, check_time },
43390926Snectar    { "no-addresses", krb5_config_string, check_boolean },
434102644Snectar    { "krb4_get_tickets", krb5_config_string, check_boolean },
435178825Sdfr    { "pkinit_anchors", krb5_config_string, NULL },
436178825Sdfr    { "pkinit_win2k", krb5_config_string, NULL },
437178825Sdfr    { "pkinit_win2k_require_binding", krb5_config_string, NULL },
438178825Sdfr    { "pkinit_require_eku", krb5_config_string, NULL },
439178825Sdfr    { "pkinit_require_krbtgt_otherName", krb5_config_string, NULL },
440178825Sdfr    { "pkinit_require_hostname_match", krb5_config_string, NULL },
44190926Snectar#if 0
44290926Snectar    { "anonymous", krb5_config_string, check_boolean },
44390926Snectar#endif
44490926Snectar    { "", krb5_config_list, appdefaults_entries },
44590926Snectar    { NULL }
44690926Snectar};
44790926Snectar
44890926Snectarstruct entry realms_entries[] = {
44990926Snectar    { "forwardable", krb5_config_string, check_boolean },
45090926Snectar    { "proxiable", krb5_config_string, check_boolean },
45190926Snectar    { "ticket_lifetime", krb5_config_string, check_time },
45290926Snectar    { "renew_lifetime", krb5_config_string, check_time },
45390926Snectar    { "warn_pwexpire", krb5_config_string, check_time },
45490926Snectar    { "kdc", krb5_config_string, check_host },
45590926Snectar    { "admin_server", krb5_config_string, check_host },
45690926Snectar    { "kpasswd_server", krb5_config_string, check_host },
45790926Snectar    { "krb524_server", krb5_config_string, check_host },
45890926Snectar    { "v4_name_convert", krb5_config_list, v4_name_convert_entries },
45990926Snectar    { "v4_instance_convert", krb5_config_list, all_strings },
46090926Snectar    { "v4_domains", krb5_config_string, NULL },
46190926Snectar    { "default_domain", krb5_config_string, NULL },
462178825Sdfr    { "win2k_pkinit", krb5_config_string, NULL },
463102644Snectar    /* MIT stuff */
464102644Snectar    { "admin_keytab", krb5_config_string, mit_entry },
465102644Snectar    { "acl_file", krb5_config_string, mit_entry },
466102644Snectar    { "dict_file", krb5_config_string, mit_entry },
467102644Snectar    { "kadmind_port", krb5_config_string, mit_entry },
468102644Snectar    { "kpasswd_port", krb5_config_string, mit_entry },
469102644Snectar    { "master_key_name", krb5_config_string, mit_entry },
470102644Snectar    { "master_key_type", krb5_config_string, mit_entry },
471102644Snectar    { "key_stash_file", krb5_config_string, mit_entry },
472102644Snectar    { "max_life", krb5_config_string, mit_entry },
473102644Snectar    { "max_renewable_life", krb5_config_string, mit_entry },
474102644Snectar    { "default_principal_expiration", krb5_config_string, mit_entry },
475102644Snectar    { "default_principal_flags", krb5_config_string, mit_entry },
476102644Snectar    { "supported_enctypes", krb5_config_string, mit_entry },
477102644Snectar    { "database_name", krb5_config_string, mit_entry },
47890926Snectar    { NULL }
47990926Snectar};
48090926Snectar
48190926Snectarstruct entry realms_foobar[] = {
48290926Snectar    { "", krb5_config_list, realms_entries },
48390926Snectar    { NULL }
48490926Snectar};
48590926Snectar
48690926Snectar
48790926Snectarstruct entry kdc_database_entries[] = {
48890926Snectar    { "realm", krb5_config_string, NULL },
48990926Snectar    { "dbname", krb5_config_string, NULL },
49090926Snectar    { "mkey_file", krb5_config_string, NULL },
491178825Sdfr    { "acl_file", krb5_config_string, NULL },
492178825Sdfr    { "log_file", krb5_config_string, NULL },
49390926Snectar    { NULL }
49490926Snectar};
49590926Snectar
49690926Snectarstruct entry kdc_entries[] = {
49790926Snectar    { "database", krb5_config_list, kdc_database_entries },
49890926Snectar    { "key-file", krb5_config_string, NULL },
499102644Snectar    { "logging", krb5_config_string, check_log },
50090926Snectar    { "max-request", krb5_config_string, check_bytes },
50190926Snectar    { "require-preauth", krb5_config_string, check_boolean },
50290926Snectar    { "ports", krb5_config_string, NULL },
50390926Snectar    { "addresses", krb5_config_string, NULL },
50490926Snectar    { "enable-kerberos4", krb5_config_string, check_boolean },
50590926Snectar    { "enable-524", krb5_config_string, check_boolean },
50690926Snectar    { "enable-http", krb5_config_string, check_boolean },
507178825Sdfr    { "check-ticket-addresses", krb5_config_string, check_boolean },
508178825Sdfr    { "allow-null-ticket-addresses", krb5_config_string, check_boolean },
50990926Snectar    { "allow-anonymous", krb5_config_string, check_boolean },
51090926Snectar    { "v4_realm", krb5_config_string, NULL },
511234027Sstas    { "enable-kaserver", krb5_config_string, check_boolean, 1 },
51290926Snectar    { "encode_as_rep_as_tgs_rep", krb5_config_string, check_boolean },
51390926Snectar    { "kdc_warn_pwexpire", krb5_config_string, check_time },
514178825Sdfr    { "use_2b", krb5_config_list, NULL },
515178825Sdfr    { "enable-pkinit", krb5_config_string, check_boolean },
516178825Sdfr    { "pkinit_identity", krb5_config_string, NULL },
517178825Sdfr    { "pkinit_anchors", krb5_config_string, NULL },
518178825Sdfr    { "pkinit_pool", krb5_config_string, NULL },
519178825Sdfr    { "pkinit_revoke", krb5_config_string, NULL },
520178825Sdfr    { "pkinit_kdc_ocsp", krb5_config_string, NULL },
521178825Sdfr    { "pkinit_principal_in_certificate", krb5_config_string, NULL },
522178825Sdfr    { "pkinit_dh_min_bits", krb5_config_string, NULL },
523178825Sdfr    { "pkinit_allow_proxy_certificate", krb5_config_string, NULL },
524178825Sdfr    { "hdb-ldap-create-base", krb5_config_string, NULL },
525178825Sdfr    { "v4-realm", krb5_config_string, NULL },
52690926Snectar    { NULL }
52790926Snectar};
52890926Snectar
52990926Snectarstruct entry kadmin_entries[] = {
53090926Snectar    { "password_lifetime", krb5_config_string, check_time },
53190926Snectar    { "default_keys", krb5_config_string, NULL },
53290926Snectar    { "use_v4_salt", krb5_config_string, NULL },
533178825Sdfr    { "require-preauth", krb5_config_string, check_boolean },
53490926Snectar    { NULL }
53590926Snectar};
536102644Snectarstruct entry log_strings[] = {
537102644Snectar    { "", krb5_config_string, check_log },
538102644Snectar    { NULL }
539102644Snectar};
540102644Snectar
541102644Snectar
542178825Sdfr/* MIT stuff */
543102644Snectarstruct entry kdcdefaults_entries[] = {
544120952Snectar    { "kdc_ports", krb5_config_string, mit_entry },
545120952Snectar    { "v4_mode", krb5_config_string, mit_entry },
546102644Snectar    { NULL }
547102644Snectar};
548102644Snectar
549178825Sdfrstruct entry capaths_entries[] = {
550178825Sdfr    { "", krb5_config_list, all_strings },
551178825Sdfr    { NULL }
552178825Sdfr};
553178825Sdfr
554178825Sdfrstruct entry password_quality_entries[] = {
555178825Sdfr    { "policies", krb5_config_string, NULL },
556178825Sdfr    { "external_program", krb5_config_string, NULL },
557178825Sdfr    { "min_classes", krb5_config_string, check_numeric },
558178825Sdfr    { "min_length", krb5_config_string, check_numeric },
559178825Sdfr    { "", krb5_config_list, all_strings },
560178825Sdfr    { NULL }
561178825Sdfr};
562178825Sdfr
56390926Snectarstruct entry toplevel_sections[] = {
56490926Snectar    { "libdefaults" , krb5_config_list, libdefaults_entries },
56590926Snectar    { "realms", krb5_config_list, realms_foobar },
56690926Snectar    { "domain_realm", krb5_config_list, all_strings },
567102644Snectar    { "logging", krb5_config_list, log_strings },
56890926Snectar    { "kdc", krb5_config_list, kdc_entries },
56990926Snectar    { "kadmin", krb5_config_list, kadmin_entries },
57090926Snectar    { "appdefaults", krb5_config_list, appdefaults_entries },
571178825Sdfr    { "gssapi", krb5_config_list, NULL },
572178825Sdfr    { "capaths", krb5_config_list, capaths_entries },
573178825Sdfr    { "password_quality", krb5_config_list, password_quality_entries },
574102644Snectar    /* MIT stuff */
575102644Snectar    { "kdcdefaults", krb5_config_list, kdcdefaults_entries },
57690926Snectar    { NULL }
57790926Snectar};
57890926Snectar
57990926Snectar
58090926Snectarstatic int
581233294Sstascheck_section(krb5_context context, const char *path, krb5_config_section *cf,
58290926Snectar	      struct entry *entries)
58390926Snectar{
58490926Snectar    int error = 0;
58590926Snectar    krb5_config_section *p;
58690926Snectar    struct entry *e;
587233294Sstas
58890926Snectar    char *local;
589233294Sstas
59090926Snectar    for(p = cf; p != NULL; p = p->next) {
591233294Sstas	local = NULL;
592233294Sstas	if (asprintf(&local, "%s/%s", path, p->name) < 0 || local == NULL)
593233294Sstas	    errx(1, "out of memory");
59490926Snectar	for(e = entries; e->name != NULL; e++) {
59590926Snectar	    if(*e->name == '\0' || strcmp(e->name, p->name) == 0) {
59690926Snectar		if(e->type != p->type) {
59790926Snectar		    krb5_warnx(context, "%s: unknown or wrong type", local);
59890926Snectar		    error |= 1;
59990926Snectar		} else if(p->type == krb5_config_string && e->check_data != NULL) {
60090926Snectar		    error |= (*(check_func_t)e->check_data)(context, local, p->u.string);
60190926Snectar		} else if(p->type == krb5_config_list && e->check_data != NULL) {
60290926Snectar		    error |= check_section(context, local, p->u.list, e->check_data);
60390926Snectar		}
604233294Sstas		if(e->deprecated) {
605233294Sstas		    krb5_warnx(context, "%s: is a deprecated entry", local);
606233294Sstas		    error |= 1;
607233294Sstas		}
60890926Snectar		break;
60990926Snectar	    }
61090926Snectar	}
61190926Snectar	if(e->name == NULL) {
61290926Snectar	    krb5_warnx(context, "%s: unknown entry", local);
61390926Snectar	    error |= 1;
61490926Snectar	}
61590926Snectar	free(local);
61690926Snectar    }
61790926Snectar    return error;
61890926Snectar}
61990926Snectar
62090926Snectar
621102644Snectarstatic void
622102644Snectardumpconfig(int level, krb5_config_section *top)
623102644Snectar{
624102644Snectar    krb5_config_section *x;
625102644Snectar    for(x = top; x; x = x->next) {
626102644Snectar	switch(x->type) {
627102644Snectar	case krb5_config_list:
628102644Snectar	    if(level == 0) {
629102644Snectar		printf("[%s]\n", x->name);
630102644Snectar	    } else {
631102644Snectar		printf("%*s%s = {\n", 4 * level, " ", x->name);
632102644Snectar	    }
633102644Snectar	    dumpconfig(level + 1, x->u.list);
634102644Snectar	    if(level > 0)
635102644Snectar		printf("%*s}\n", 4 * level, " ");
636102644Snectar	    break;
637102644Snectar	case krb5_config_string:
638102644Snectar	    printf("%*s%s = %s\n", 4 * level, " ", x->name, x->u.string);
639102644Snectar	    break;
640102644Snectar	}
641102644Snectar    }
642102644Snectar}
643102644Snectar
64455682Smarkmint
64555682Smarkmmain(int argc, char **argv)
64655682Smarkm{
64778527Sassar    krb5_context context;
64855682Smarkm    krb5_error_code ret;
64955682Smarkm    krb5_config_section *tmp_cf;
650178825Sdfr    int optidx = 0;
65155682Smarkm
65278527Sassar    setprogname (argv[0]);
65355682Smarkm
65478527Sassar    ret = krb5_init_context(&context);
655178825Sdfr    if (ret == KRB5_CONFIG_BADFORMAT)
656178825Sdfr	errx (1, "krb5_init_context failed to parse configuration file");
657178825Sdfr    else if (ret)
658178825Sdfr	errx (1, "krb5_init_context failed with %d", ret);
65978527Sassar
660178825Sdfr    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
66155682Smarkm	usage(1);
662233294Sstas
66355682Smarkm    if (help_flag)
66455682Smarkm	usage (0);
66555682Smarkm
66655682Smarkm    if(version_flag){
66755682Smarkm	print_version(NULL);
66855682Smarkm	exit(0);
66955682Smarkm    }
67055682Smarkm
671178825Sdfr    argc -= optidx;
672178825Sdfr    argv += optidx;
67355682Smarkm
674102644Snectar    tmp_cf = NULL;
675102644Snectar    if(argc == 0)
676102644Snectar	krb5_get_default_config_files(&argv);
677102644Snectar
678102644Snectar    while(*argv) {
679102644Snectar	ret = krb5_config_parse_file_multi(context, *argv, &tmp_cf);
680102644Snectar	if (ret != 0)
681102644Snectar	    krb5_warn (context, ret, "krb5_config_parse_file");
682102644Snectar	argv++;
68355682Smarkm    }
684102644Snectar
685102644Snectar    if(dumpconfig_flag)
686102644Snectar	dumpconfig(0, tmp_cf);
687233294Sstas
68890926Snectar    return check_section(context, "", tmp_cf, toplevel_sections);
68955682Smarkm}
690