config.c revision 102644
1/*
2 * Copyright (c) 1997-2002 Kungliga Tekniska H�gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "kdc_locl.h"
35#include <getarg.h>
36#include <parse_bytes.h>
37
38RCSID("$Id: config.c,v 1.43 2002/08/29 01:51:07 assar Exp $");
39
40static const char *config_file;	/* location of kdc config file */
41
42int require_preauth = -1;	/* 1 == require preauth for all principals */
43
44size_t max_request;		/* maximal size of a request */
45
46static char *max_request_str;	/* `max_request' as a string */
47
48time_t kdc_warn_pwexpire;	/* time before expiration to print a warning */
49
50struct dbinfo *databases;
51HDB **db;
52int num_db;
53
54const char *port_str;
55
56#ifdef HAVE_DAEMON
57int detach_from_console = -1;
58#define DETACH_IS_DEFAULT FALSE
59#endif
60
61int enable_http = -1;
62krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */
63
64krb5_boolean check_ticket_addresses;
65krb5_boolean allow_null_ticket_addresses;
66krb5_boolean allow_anonymous;
67
68static struct getarg_strings addresses_str;	/* addresses to listen on */
69krb5_addresses explicit_addresses;
70
71#ifdef KRB4
72char *v4_realm;
73int enable_v4 = -1;
74int enable_524 = -1;
75int enable_kaserver = -1;
76#endif
77
78static int help_flag;
79static int version_flag;
80
81static struct getargs args[] = {
82    {
83	"config-file",	'c',	arg_string,	&config_file,
84	"location of config file",	"file"
85    },
86    {
87	"require-preauth",	'p',	arg_negative_flag, &require_preauth,
88	"don't require pa-data in as-reqs"
89    },
90    {
91	"max-request",	0,	arg_string, &max_request,
92	"max size for a kdc-request", "size"
93    },
94#if 0
95    {
96	"database",	'd', 	arg_string, &databases,
97	"location of database", "database"
98    },
99#endif
100    { "enable-http", 'H', arg_flag, &enable_http, "turn on HTTP support" },
101#ifdef KRB4
102    {	"kerberos4",	0, 	arg_negative_flag, &enable_v4,
103	"don't respond to kerberos 4 requests"
104    },
105    {	"524",		0, 	arg_negative_flag, &enable_524,
106	"don't respond to 524 requests"
107    },
108    {
109	"v4-realm",	'r',	arg_string, &v4_realm,
110	"realm to serve v4-requests for"
111    },
112    {
113	"kaserver", 'K', arg_flag,   &enable_kaserver,
114	"enable kaserver support"
115    },
116#endif
117    {	"ports",	'P', 	arg_string, &port_str,
118	"ports to listen to", "portspec"
119    },
120#ifdef HAVE_DAEMON
121#if DETACH_IS_DEFAULT
122    {
123	"detach",       'D',      arg_negative_flag, &detach_from_console,
124	"don't detach from console"
125    },
126#else
127    {
128	"detach",       0 ,      arg_flag, &detach_from_console,
129	"detach from console"
130    },
131#endif
132#endif
133    {	"addresses",	0,	arg_strings, &addresses_str,
134	"addresses to listen on", "list of addresses" },
135    {	"help",		'h',	arg_flag,   &help_flag },
136    {	"version",	'v',	arg_flag,   &version_flag }
137};
138
139static int num_args = sizeof(args) / sizeof(args[0]);
140
141static void
142usage(int ret)
143{
144    arg_printusage (args, num_args, NULL, "");
145    exit (ret);
146}
147
148static void
149get_dbinfo(void)
150{
151    const krb5_config_binding *top_binding = NULL;
152    const krb5_config_binding *db_binding;
153    const krb5_config_binding *default_binding = NULL;
154    struct dbinfo *di, **dt;
155    const char *default_dbname = HDB_DEFAULT_DB;
156    const char *default_mkey = HDB_DB_DIR "/m-key";
157    const char *p;
158
159    databases = NULL;
160    dt = &databases;
161    while((db_binding = (const krb5_config_binding *)
162	   krb5_config_get_next(context, NULL, &top_binding,
163				krb5_config_list,
164				"kdc",
165				"database",
166				NULL))) {
167	p = krb5_config_get_string(context, db_binding, "realm", NULL);
168	if(p == NULL) {
169	    if(default_binding) {
170		krb5_warnx(context, "WARNING: more than one realm-less "
171			   "database specification");
172		krb5_warnx(context, "WARNING: using the first encountered");
173	    } else
174		default_binding = db_binding;
175	    continue;
176	}
177	di = calloc(1, sizeof(*di));
178	di->realm = strdup(p);
179	p = krb5_config_get_string(context, db_binding, "dbname", NULL);
180	if(p)
181	    di->dbname = strdup(p);
182	p = krb5_config_get_string(context, db_binding, "mkey_file", NULL);
183	if(p)
184	    di->mkey_file = strdup(p);
185	*dt = di;
186	dt = &di->next;
187    }
188    if(default_binding) {
189	di = calloc(1, sizeof(*di));
190	p = krb5_config_get_string(context, default_binding, "dbname", NULL);
191	if(p) {
192	    di->dbname = strdup(p);
193	    default_dbname = p;
194	}
195	p = krb5_config_get_string(context, default_binding, "mkey_file", NULL);
196	if(p) {
197	    di->mkey_file = strdup(p);
198	    default_mkey = p;
199	}
200	*dt = di;
201	dt = &di->next;
202    } else if(databases == NULL) {
203	/* if there are none specified, use some default */
204	di = calloc(1, sizeof(*di));
205	di->dbname = strdup(default_dbname);
206	di->mkey_file = strdup(default_mkey);
207	*dt = di;
208	dt = &di->next;
209    }
210    for(di = databases; di; di = di->next) {
211	if(di->dbname == NULL)
212	    di->dbname = strdup(default_dbname);
213	if(di->mkey_file == NULL) {
214	    p = strrchr(di->dbname, '.');
215	    if(p == NULL || strchr(p, '/') != NULL)
216		/* final pathname component does not contain a . */
217		asprintf(&di->mkey_file, "%s.mkey", di->dbname);
218	    else
219		/* the filename is something.else, replace .else with
220                   .mkey */
221		asprintf(&di->mkey_file, "%.*s.mkey",
222			 (int)(p - di->dbname), di->dbname);
223	}
224    }
225}
226
227static void
228add_one_address (const char *str, int first)
229{
230    krb5_error_code ret;
231    krb5_addresses tmp;
232
233    ret = krb5_parse_address (context, str, &tmp);
234    if (ret)
235	krb5_err (context, 1, ret, "parse_address `%s'", str);
236    if (first)
237	krb5_copy_addresses(context, &tmp, &explicit_addresses);
238    else
239	krb5_append_addresses(context, &explicit_addresses, &tmp);
240    krb5_free_addresses (context, &tmp);
241}
242
243void
244configure(int argc, char **argv)
245{
246    int optind = 0;
247    int e;
248    const char *p;
249
250    while((e = getarg(args, num_args, argc, argv, &optind)))
251	warnx("error at argument `%s'", argv[optind]);
252
253    if(help_flag)
254	usage (0);
255
256    if (version_flag) {
257	print_version(NULL);
258	exit(0);
259    }
260
261    argc -= optind;
262    argv += optind;
263
264    if (argc != 0)
265	usage(1);
266
267    {
268	krb5_error_code ret;
269	char **files;
270	char *tmp;
271	if(config_file == NULL)
272	    config_file = _PATH_KDC_CONF;
273	asprintf(&tmp, "%s:%s", config_file, krb5_config_file);
274	if(tmp == NULL)
275	    krb5_errx(context, 1, "out of memory");
276
277	krb5_config_file = tmp;
278
279	ret = krb5_get_default_config_files(&files);
280	if(ret)
281	    krb5_err(context, 1, ret, "reading configuration files");
282	ret = krb5_set_config_files(context, files);
283	krb5_free_config_files(files);
284	if(ret)
285	    krb5_err(context, 1, ret, "reading configuration files");
286    }
287
288    get_dbinfo();
289
290    if(max_request_str){
291	max_request = parse_bytes(max_request_str, NULL);
292    }
293
294    if(max_request == 0){
295	p = krb5_config_get_string (context,
296				    NULL,
297				    "kdc",
298				    "max-request",
299				    NULL);
300	if(p)
301	    max_request = parse_bytes(p, NULL);
302    }
303
304    if(require_preauth == -1)
305	require_preauth = krb5_config_get_bool(context, NULL, "kdc",
306					       "require-preauth", NULL);
307
308    if(port_str == NULL){
309	p = krb5_config_get_string(context, NULL, "kdc", "ports", NULL);
310	if (p != NULL)
311	    port_str = strdup(p);
312    }
313
314    explicit_addresses.len = 0;
315
316    if (addresses_str.num_strings) {
317	int i;
318
319	for (i = 0; i < addresses_str.num_strings; ++i)
320	    add_one_address (addresses_str.strings[i], i == 0);
321	free_getarg_strings (&addresses_str);
322    } else {
323	char **foo = krb5_config_get_strings (context, NULL,
324					      "kdc", "addresses", NULL);
325
326	if (foo != NULL) {
327	    add_one_address (*foo++, TRUE);
328	    while (*foo)
329		add_one_address (*foo++, FALSE);
330	}
331    }
332
333#ifdef KRB4
334    if(enable_v4 == -1)
335	enable_v4 = krb5_config_get_bool_default(context, NULL, TRUE, "kdc",
336					 "enable-kerberos4", NULL);
337    if(enable_524 == -1)
338	enable_524 = krb5_config_get_bool_default(context, NULL, enable_v4,
339						  "kdc", "enable-524", NULL);
340#endif
341
342    if(enable_http == -1)
343	enable_http = krb5_config_get_bool(context, NULL, "kdc",
344					   "enable-http", NULL);
345    check_ticket_addresses =
346	krb5_config_get_bool_default(context, NULL, TRUE, "kdc",
347				     "check-ticket-addresses", NULL);
348    allow_null_ticket_addresses =
349	krb5_config_get_bool_default(context, NULL, TRUE, "kdc",
350				     "allow-null-ticket-addresses", NULL);
351
352    allow_anonymous =
353	krb5_config_get_bool(context, NULL, "kdc",
354			     "allow-anonymous", NULL);
355#ifdef KRB4
356    if(v4_realm == NULL){
357	p = krb5_config_get_string (context, NULL,
358				    "kdc",
359				    "v4-realm",
360				    NULL);
361	if(p)
362	    v4_realm = strdup(p);
363    }
364    if (enable_kaserver == -1)
365	enable_kaserver = krb5_config_get_bool_default(context, NULL, FALSE,
366						       "kdc",
367						       "enable-kaserver",
368						       NULL);
369#endif
370
371    encode_as_rep_as_tgs_rep = krb5_config_get_bool(context, NULL, "kdc",
372						    "encode_as_rep_as_tgs_rep",
373						    NULL);
374
375    kdc_warn_pwexpire = krb5_config_get_time (context, NULL,
376					      "kdc",
377					      "kdc_warn_pwexpire",
378					      NULL);
379
380#ifdef HAVE_DAEMON
381    if(detach_from_console == -1)
382	detach_from_console = krb5_config_get_bool_default(context, NULL,
383							   DETACH_IS_DEFAULT,
384							   "kdc",
385							   "detach", NULL);
386#endif
387    kdc_openlog();
388    if(max_request == 0)
389	max_request = 64 * 1024;
390    if(require_preauth == -1)
391	require_preauth = 1;
392    if (port_str == NULL)
393	port_str = "+";
394#ifdef KRB4
395    if(v4_realm == NULL){
396	v4_realm = malloc(40); /* REALM_SZ */
397	krb_get_lrealm(v4_realm, 1);
398    }
399#endif
400}
401