xref: /freebsd/crypto/heimdal/kdc/config.c (revision a3e8fd0b7f663db7eafff527d5c3ca3bcfa8a537)
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 
38 RCSID("$Id: config.c,v 1.43 2002/08/29 01:51:07 assar Exp $");
39 
40 static const char *config_file;	/* location of kdc config file */
41 
42 int require_preauth = -1;	/* 1 == require preauth for all principals */
43 
44 size_t max_request;		/* maximal size of a request */
45 
46 static char *max_request_str;	/* `max_request' as a string */
47 
48 time_t kdc_warn_pwexpire;	/* time before expiration to print a warning */
49 
50 struct dbinfo *databases;
51 HDB **db;
52 int num_db;
53 
54 const char *port_str;
55 
56 #ifdef HAVE_DAEMON
57 int detach_from_console = -1;
58 #define DETACH_IS_DEFAULT FALSE
59 #endif
60 
61 int enable_http = -1;
62 krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */
63 
64 krb5_boolean check_ticket_addresses;
65 krb5_boolean allow_null_ticket_addresses;
66 krb5_boolean allow_anonymous;
67 
68 static struct getarg_strings addresses_str;	/* addresses to listen on */
69 krb5_addresses explicit_addresses;
70 
71 #ifdef KRB4
72 char *v4_realm;
73 int enable_v4 = -1;
74 int enable_524 = -1;
75 int enable_kaserver = -1;
76 #endif
77 
78 static int help_flag;
79 static int version_flag;
80 
81 static 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 
139 static int num_args = sizeof(args) / sizeof(args[0]);
140 
141 static void
142 usage(int ret)
143 {
144     arg_printusage (args, num_args, NULL, "");
145     exit (ret);
146 }
147 
148 static void
149 get_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 
227 static void
228 add_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 
243 void
244 configure(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