1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/kadm5/alt_prof.c */
3 /*
4 * Copyright 1995,2001,2008,2009 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 */
26 /*
27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 /* Implement alternate profile file handling. */
32 #include "k5-int.h"
33 #include "fake-addrinfo.h"
34 #include <kadm5/admin.h>
35 #include "adm_proto.h"
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <kdb_log.h>
39
40 static krb5_key_salt_tuple *
copy_key_salt_tuple(krb5_key_salt_tuple * ksalt,krb5_int32 len)41 copy_key_salt_tuple(krb5_key_salt_tuple *ksalt, krb5_int32 len)
42 {
43 krb5_key_salt_tuple *knew;
44
45 knew = calloc(len, sizeof(krb5_key_salt_tuple));
46 if (knew == NULL)
47 return NULL;
48 memcpy(knew, ksalt, len * sizeof(krb5_key_salt_tuple));
49 return knew;
50 }
51
52 /*
53 * krb5_aprof_getvals() - Get values from alternate profile.
54 *
55 * Parameters:
56 * acontext - opaque context for alternate profile.
57 * hierarchy - hierarchy of value to retrieve.
58 * retdata - Returned data values.
59 *
60 * Returns:
61 * error codes from profile_get_values()
62 */
63 krb5_error_code
krb5_aprof_getvals(krb5_pointer acontext,const char ** hierarchy,char *** retdata)64 krb5_aprof_getvals(krb5_pointer acontext, const char **hierarchy,
65 char ***retdata)
66 {
67 return profile_get_values(acontext, hierarchy, retdata);
68 }
69
70 /*
71 * krb5_aprof_get_boolean()
72 *
73 * Parameters:
74 * acontext - opaque context for alternate profile
75 * hierarchy - hierarchy of value to retrieve
76 * retdata - Returned data value
77 * Returns:
78 * error codes
79 */
80
81 static krb5_error_code
string_to_boolean(const char * string,krb5_boolean * out)82 string_to_boolean(const char *string, krb5_boolean *out)
83 {
84 static const char *const yes[] = { "y", "yes", "true", "t", "1", "on" };
85 static const char *const no[] = { "n", "no", "false", "f", "nil", "0",
86 "off" };
87 unsigned int i;
88
89 for (i = 0; i < sizeof(yes) / sizeof(yes[0]); i++) {
90 if (!strcasecmp(string, yes[i])) {
91 *out = TRUE;
92 return 0;
93 }
94 }
95 for (i = 0; i < sizeof(no) / sizeof(no[0]); i++) {
96 if (!strcasecmp(string, no[i])) {
97 *out = FALSE;
98 return 0;
99 }
100 }
101 return PROF_BAD_BOOLEAN;
102 }
103
104 krb5_error_code
krb5_aprof_get_boolean(krb5_pointer acontext,const char ** hierarchy,int uselast,krb5_boolean * retdata)105 krb5_aprof_get_boolean(krb5_pointer acontext, const char **hierarchy,
106 int uselast, krb5_boolean *retdata)
107 {
108 krb5_error_code ret;
109 char **values, *valp;
110 int idx;
111 krb5_boolean val;
112
113 ret = krb5_aprof_getvals(acontext, hierarchy, &values);
114 if (ret)
115 return ret;
116 idx = 0;
117 if (uselast) {
118 while (values[idx] != NULL)
119 idx++;
120 idx--;
121 }
122 valp = values[idx];
123 ret = string_to_boolean(valp, &val);
124 profile_free_list(values);
125 if (ret)
126 return ret;
127 *retdata = val;
128 return 0;
129 }
130
131 /*
132 * krb5_aprof_get_deltat() - Get a delta time value from the alternate
133 * profile.
134 *
135 * Parameters:
136 * acontext - opaque context for alternate profile.
137 * hierarchy - hierarchy of value to retrieve.
138 * uselast - if true, use last value, otherwise use first
139 * value found.
140 * deltatp - returned delta time value.
141 *
142 * Returns:
143 * error codes from profile_get_values()
144 * error codes from krb5_string_to_deltat()
145 */
146 krb5_error_code
krb5_aprof_get_deltat(krb5_pointer acontext,const char ** hierarchy,krb5_boolean uselast,krb5_deltat * deltatp)147 krb5_aprof_get_deltat(krb5_pointer acontext, const char **hierarchy,
148 krb5_boolean uselast, krb5_deltat *deltatp)
149 {
150 krb5_error_code ret;
151 char **values, *valp;
152 int idx;
153
154 ret = krb5_aprof_getvals(acontext, hierarchy, &values);
155 if (ret)
156 return ret;
157
158 idx = 0;
159 if (uselast) {
160 for (idx = 0; values[idx] != NULL; idx++);
161 idx--;
162 }
163 valp = values[idx];
164
165 ret = krb5_string_to_deltat(valp, deltatp);
166 profile_free_list(values);
167 return ret;
168 }
169
170 /*
171 * krb5_aprof_get_string() - Get a string value from the alternate profile.
172 *
173 * Parameters:
174 * acontext - opaque context for alternate profile.
175 * hierarchy - hierarchy of value to retrieve.
176 * uselast - if true, use last value, otherwise use first
177 * value found.
178 * stringp - returned string value.
179 *
180 * Returns:
181 * error codes from profile_get_values()
182 */
183 krb5_error_code
krb5_aprof_get_string(krb5_pointer acontext,const char ** hierarchy,krb5_boolean uselast,char ** stringp)184 krb5_aprof_get_string(krb5_pointer acontext, const char **hierarchy,
185 krb5_boolean uselast, char **stringp)
186 {
187 krb5_error_code ret;
188 char **values;
189 int lastidx;
190
191 ret = krb5_aprof_getvals(acontext, hierarchy, &values);
192 if (ret)
193 return ret;
194
195 for (lastidx = 0; values[lastidx] != NULL; lastidx++);
196 lastidx--;
197
198 /* Excise the entry we want from the null-terminated list,
199 * and free up the rest. */
200 if (uselast) {
201 *stringp = values[lastidx];
202 values[lastidx] = NULL;
203 } else {
204 *stringp = values[0];
205 values[0] = values[lastidx];
206 values[lastidx] = NULL;
207 }
208
209 profile_free_list(values);
210 return 0;
211 }
212
213 /*
214 * krb5_aprof_get_string_all() - When the attr identified by "hierarchy" is
215 * specified multiple times, concatenate all of
216 * its string values from the alternate profile,
217 * separated with spaces.
218 *
219 * Parameters:
220 * acontext - opaque context for alternate profile.
221 * hierarchy - hierarchy of value to retrieve.
222 * stringp - Returned string value.
223 *
224 * Returns:
225 * error codes from profile_get_values() or ENOMEM
226 * Caller is responsible for deallocating stringp buffer
227 */
228 krb5_error_code
krb5_aprof_get_string_all(krb5_pointer acontext,const char ** hierarchy,char ** stringp)229 krb5_aprof_get_string_all(krb5_pointer acontext, const char **hierarchy,
230 char **stringp)
231 {
232 krb5_error_code ret;
233 char **values;
234 int idx = 0;
235 size_t buf_size = 0;
236
237 ret = krb5_aprof_getvals(acontext, hierarchy, &values);
238 if (ret)
239 return ret;
240
241 buf_size = strlen(values[0]) + 3;
242 for (idx = 1; values[idx] != NULL; idx++)
243 buf_size += strlen(values[idx]) + 3;
244
245 *stringp = calloc(1, buf_size);
246 if (*stringp == NULL) {
247 profile_free_list(values);
248 return ENOMEM;
249 }
250 strlcpy(*stringp, values[0], buf_size);
251 for (idx = 1; values[idx] != NULL; idx++) {
252 strlcat(*stringp, " ", buf_size);
253 strlcat(*stringp, values[idx], buf_size);
254 }
255
256 profile_free_list(values);
257 return 0;
258 }
259
260
261 /*
262 * krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate
263 * profile.
264 *
265 * Parameters:
266 * acontext - opaque context for alternate profile.
267 * hierarchy - hierarchy of value to retrieve.
268 * uselast - if true, use last value, otherwise use first
269 * value found.
270 * intp - returned 32-bit integer value.
271 *
272 * Returns:
273 * error codes from profile_get_values()
274 * EINVAL - value is not an integer
275 */
276 krb5_error_code
krb5_aprof_get_int32(krb5_pointer acontext,const char ** hierarchy,krb5_boolean uselast,krb5_int32 * intp)277 krb5_aprof_get_int32(krb5_pointer acontext, const char **hierarchy,
278 krb5_boolean uselast, krb5_int32 *intp)
279 {
280 krb5_error_code ret;
281 char **values;
282 int idx;
283
284 ret = krb5_aprof_getvals(acontext, hierarchy, &values);
285 if (ret)
286 return ret;
287
288 idx = 0;
289 if (uselast) {
290 for (idx = 0; values[idx] != NULL; idx++);
291 idx--;
292 }
293
294 if (sscanf(values[idx], "%d", intp) != 1)
295 ret = EINVAL;
296
297 profile_free_list(values);
298 return ret;
299 }
300
301 /*
302 * Returns nonzero if it found something to copy; the caller may still need to
303 * check the output field or mask to see if the copy (allocation) was
304 * successful. Returns zero if nothing was found to copy, and thus the caller
305 * may want to apply some default heuristic. If the default action is just to
306 * use a fixed, compiled-in string, supply it as the default value here and
307 * ignore the return value.
308 */
309 static int
get_string_param(char ** param_out,char * param_in,long * mask_out,long mask_in,long mask_bit,krb5_pointer aprofile,const char ** hierarchy,const char * config_name,const char * default_value)310 get_string_param(char **param_out, char *param_in, long *mask_out,
311 long mask_in, long mask_bit, krb5_pointer aprofile,
312 const char **hierarchy, const char *config_name,
313 const char *default_value)
314 {
315 char *svalue;
316
317 hierarchy[2] = config_name;
318 if (mask_in & mask_bit) {
319 *param_out = strdup(param_in);
320 if (*param_out)
321 *mask_out |= mask_bit;
322 return 1;
323 } else if (aprofile != NULL &&
324 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
325 *param_out = svalue;
326 *mask_out |= mask_bit;
327 return 1;
328 } else if (default_value) {
329 *param_out = strdup(default_value);
330 if (*param_out)
331 *mask_out |= mask_bit;
332 return 1;
333 } else {
334 return 0;
335 }
336 }
337 /*
338 * Similar, for (host-order) port number, if not already set in the output
339 * field; default_value == 0 means no default.
340 */
341 static void
get_port_param(int * param_out,int param_in,long * mask_out,long mask_in,long mask_bit,krb5_pointer aprofile,const char ** hierarchy,const char * config_name,int default_value)342 get_port_param(int *param_out, int param_in, long *mask_out, long mask_in,
343 long mask_bit, krb5_pointer aprofile, const char **hierarchy,
344 const char *config_name, int default_value)
345 {
346 krb5_int32 ivalue;
347
348 if (*mask_out & mask_bit)
349 return;
350 hierarchy[2] = config_name;
351 if (mask_in & mask_bit) {
352 *mask_out |= mask_bit;
353 *param_out = param_in;
354 } else if (aprofile != NULL &&
355 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {
356 *param_out = ivalue;
357 *mask_out |= mask_bit;
358 } else if (default_value) {
359 *param_out = default_value;
360 *mask_out |= mask_bit;
361 }
362 }
363
364 /*
365 * Similar, for delta_t; default is required.
366 */
367 static void
get_deltat_param(krb5_deltat * param_out,krb5_deltat param_in,long * mask_out,long mask_in,long mask_bit,krb5_pointer aprofile,const char ** hierarchy,const char * config_name,krb5_deltat default_value)368 get_deltat_param(krb5_deltat *param_out, krb5_deltat param_in, long *mask_out,
369 long mask_in, long mask_bit, krb5_pointer aprofile,
370 const char **hierarchy, const char *config_name,
371 krb5_deltat default_value)
372 {
373 krb5_deltat dtvalue;
374
375 hierarchy[2] = config_name;
376 if (mask_in & mask_bit) {
377 *mask_out |= mask_bit;
378 *param_out = param_in;
379 } else if (aprofile &&
380 !krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
381 *param_out = dtvalue;
382 *mask_out |= mask_bit;
383 } else {
384 *param_out = default_value;
385 *mask_out |= mask_bit;
386 }
387 }
388
389 /*
390 * Parse out the port number from an admin_server setting. Modify server to
391 * contain just the hostname or address. If a port is given, set *port, and
392 * set the appropriate bit in *mask.
393 */
394 static void
parse_admin_server_port(char * server,int * port,long * mask)395 parse_admin_server_port(char *server, int *port, long *mask)
396 {
397 char *end, *portstr;
398
399 /* Allow the name or addr to be enclosed in brackets, for IPv6 addrs. */
400 if (*server == '[' && (end = strchr(server + 1, ']')) != NULL) {
401 portstr = (*(end + 1) == ':') ? end + 2 : NULL;
402 /* Shift the bracketed name or address back into server. */
403 memmove(server, server + 1, end - (server + 1));
404 *(end - 1) = '\0';
405 } else {
406 /* Terminate the name at the colon, if any. */
407 end = server + strcspn(server, ":");
408 portstr = (*end == ':') ? end + 1 : NULL;
409 *end = '\0';
410 }
411
412 /* If we found a port string, parse it and set the appropriate bit. */
413 if (portstr) {
414 *port = atoi(portstr);
415 *mask |= KADM5_CONFIG_KADMIND_PORT;
416 }
417 }
418
419 /*
420 * Function: kadm5_get_config_params
421 *
422 * Purpose: Merge configuration parameters provided by the caller with values
423 * specified in configuration files and with default values.
424 *
425 * Arguments:
426 *
427 * context (r) krb5_context to use
428 * profile (r) profile file to use
429 * envname (r) envname that contains a profile name to
430 * override profile
431 * params_in (r) params structure containing user-supplied
432 * values, or NULL
433 * params_out (w) params structure to be filled in
434 *
435 * Effects:
436 *
437 * The fields and mask of params_out are filled in with values obtained from
438 * params_in, the specified profile, and default values. Only and all fields
439 * specified in params_out->mask are set. The context of params_out must be
440 * freed with kadm5_free_config_params.
441 *
442 * params_in and params_out may be the same pointer. However, all pointers in
443 * params_in for which the mask is set will be re-assigned to newly copied
444 * versions, overwriting the old pointer value.
445 */
kadm5_get_config_params(krb5_context context,int use_kdc_config,kadm5_config_params * params_in,kadm5_config_params * params_out)446 krb5_error_code kadm5_get_config_params(krb5_context context,
447 int use_kdc_config,
448 kadm5_config_params *params_in,
449 kadm5_config_params *params_out)
450 {
451 char *lrealm, *svalue, *sp, *ep, *tp;
452 krb5_pointer aprofile = context->profile;
453 const char *hierarchy[4];
454 krb5_int32 ivalue;
455 kadm5_config_params params, empty_params;
456 krb5_boolean bvalue;
457 krb5_error_code ret = 0;
458
459 memset(¶ms, 0, sizeof(params));
460 memset(&empty_params, 0, sizeof(empty_params));
461
462 if (params_in == NULL)
463 params_in = &empty_params;
464
465 if (params_in->mask & KADM5_CONFIG_REALM) {
466 lrealm = params.realm = strdup(params_in->realm);
467 if (params.realm == NULL) {
468 ret = ENOMEM;
469 goto cleanup;
470 }
471 params.mask |= KADM5_CONFIG_REALM;
472 } else {
473 ret = krb5_get_default_realm(context, &lrealm);
474 if (ret)
475 goto cleanup;
476 params.realm = lrealm;
477 params.mask |= KADM5_CONFIG_REALM;
478 }
479
480 if (params_in->mask & KADM5_CONFIG_KVNO) {
481 params.kvno = params_in->kvno;
482 params.mask |= KADM5_CONFIG_KVNO;
483 }
484
485 /* Initialize realm parameters. */
486 hierarchy[0] = KRB5_CONF_REALMS;
487 hierarchy[1] = lrealm;
488 hierarchy[3] = NULL;
489
490 #define GET_STRING_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \
491 get_string_param(¶ms.FIELD, params_in->FIELD, \
492 ¶ms.mask, params_in->mask, BIT, \
493 aprofile, hierarchy, CONFTAG, DEFAULT)
494
495 /* Get the value for the admin server. */
496 GET_STRING_PARAM(admin_server, KADM5_CONFIG_ADMIN_SERVER,
497 KRB5_CONF_ADMIN_SERVER, NULL);
498
499 if (params.mask & KADM5_CONFIG_ADMIN_SERVER) {
500 parse_admin_server_port(params.admin_server, ¶ms.kadmind_port,
501 ¶ms.mask);
502 }
503
504 /* Get the value for the database. */
505 GET_STRING_PARAM(dbname, KADM5_CONFIG_DBNAME, KRB5_CONF_DATABASE_NAME,
506 DEFAULT_KDB_FILE);
507
508 /* Get the name of the acl file. */
509 GET_STRING_PARAM(acl_file, KADM5_CONFIG_ACL_FILE, KRB5_CONF_ACL_FILE,
510 DEFAULT_KADM5_ACL_FILE);
511
512 /* Get the name of the dict file. */
513 GET_STRING_PARAM(dict_file, KADM5_CONFIG_DICT_FILE, KRB5_CONF_DICT_FILE,
514 NULL);
515
516 /* Get the kadmind listen addresses. */
517 GET_STRING_PARAM(kadmind_listen, KADM5_CONFIG_KADMIND_LISTEN,
518 KRB5_CONF_KADMIND_LISTEN, NULL);
519 GET_STRING_PARAM(kpasswd_listen, KADM5_CONFIG_KPASSWD_LISTEN,
520 KRB5_CONF_KPASSWD_LISTEN, NULL);
521 GET_STRING_PARAM(iprop_listen, KADM5_CONFIG_IPROP_LISTEN,
522 KRB5_CONF_IPROP_LISTEN, NULL);
523
524 #define GET_PORT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \
525 get_port_param(¶ms.FIELD, params_in->FIELD, \
526 ¶ms.mask, params_in->mask, BIT, \
527 aprofile, hierarchy, CONFTAG, DEFAULT)
528
529 /* Get the value for the kadmind port. */
530 GET_PORT_PARAM(kadmind_port, KADM5_CONFIG_KADMIND_PORT,
531 KRB5_CONF_KADMIND_PORT, DEFAULT_KADM5_PORT);
532
533 /* Get the value for the kpasswd port. */
534 GET_PORT_PARAM(kpasswd_port, KADM5_CONFIG_KPASSWD_PORT,
535 KRB5_CONF_KPASSWD_PORT, DEFAULT_KPASSWD_PORT);
536
537 /* Get the value for the master key name. */
538 GET_STRING_PARAM(mkey_name, KADM5_CONFIG_MKEY_NAME,
539 KRB5_CONF_MASTER_KEY_NAME, NULL);
540
541 /* Get the value for the master key type. */
542 hierarchy[2] = KRB5_CONF_MASTER_KEY_TYPE;
543 if (params_in->mask & KADM5_CONFIG_ENCTYPE) {
544 params.mask |= KADM5_CONFIG_ENCTYPE;
545 params.enctype = params_in->enctype;
546 } else if (aprofile != NULL &&
547 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
548 if (!krb5_string_to_enctype(svalue, ¶ms.enctype)) {
549 params.mask |= KADM5_CONFIG_ENCTYPE;
550 free(svalue);
551 }
552 } else {
553 params.mask |= KADM5_CONFIG_ENCTYPE;
554 params.enctype = DEFAULT_KDC_ENCTYPE;
555 }
556
557 /* Get the value for mkey_from_kbd. */
558 if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) {
559 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
560 params.mkey_from_kbd = params_in->mkey_from_kbd;
561 }
562
563 /* Get the value for the stashfile. */
564 GET_STRING_PARAM(stash_file, KADM5_CONFIG_STASH_FILE,
565 KRB5_CONF_KEY_STASH_FILE, NULL);
566
567 /* Get the value for maximum ticket lifetime. */
568 #define GET_DELTAT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \
569 get_deltat_param(¶ms.FIELD, params_in->FIELD, \
570 ¶ms.mask, params_in->mask, BIT, \
571 aprofile, hierarchy, CONFTAG, DEFAULT)
572
573 GET_DELTAT_PARAM(max_life, KADM5_CONFIG_MAX_LIFE, KRB5_CONF_MAX_LIFE,
574 24 * 60 * 60); /* 1 day */
575
576 /* Get the value for maximum renewable ticket lifetime. */
577 GET_DELTAT_PARAM(max_rlife, KADM5_CONFIG_MAX_RLIFE,
578 KRB5_CONF_MAX_RENEWABLE_LIFE, 0);
579
580 /* Get the value for the default principal expiration */
581 hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION;
582 if (params_in->mask & KADM5_CONFIG_EXPIRATION) {
583 params.mask |= KADM5_CONFIG_EXPIRATION;
584 params.expiration = params_in->expiration;
585 } else if (aprofile &&
586 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
587 if (!krb5_string_to_timestamp(svalue, ¶ms.expiration)) {
588 params.mask |= KADM5_CONFIG_EXPIRATION;
589 free(svalue);
590 }
591 } else {
592 params.mask |= KADM5_CONFIG_EXPIRATION;
593 params.expiration = 0;
594 }
595
596 /* Get the value for the default principal flags */
597 hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS;
598 if (params_in->mask & KADM5_CONFIG_FLAGS) {
599 params.mask |= KADM5_CONFIG_FLAGS;
600 params.flags = params_in->flags;
601 } else if (aprofile != NULL &&
602 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
603 sp = svalue;
604 params.flags = 0;
605 while (sp != NULL) {
606 if ((ep = strchr(sp, ',')) != NULL ||
607 (ep = strchr(sp, ' ')) != NULL ||
608 (ep = strchr(sp, '\t')) != NULL) {
609 /* Fill in trailing whitespace of sp. */
610 tp = ep - 1;
611 while (isspace((unsigned char)*tp) && tp > sp) {
612 *tp = '\0';
613 tp--;
614 }
615 *ep = '\0';
616 ep++;
617 /* Skip over trailing whitespace of ep. */
618 while (isspace((unsigned char)*ep) && *ep != '\0')
619 ep++;
620 }
621 /* Convert this flag. */
622 if (krb5_flagspec_to_mask(sp, ¶ms.flags, ¶ms.flags))
623 break;
624 sp = ep;
625 }
626 if (sp == NULL)
627 params.mask |= KADM5_CONFIG_FLAGS;
628 free(svalue);
629 } else {
630 params.mask |= KADM5_CONFIG_FLAGS;
631 params.flags = KRB5_KDB_DEF_FLAGS;
632 }
633
634 /* Get the value for the supported enctype/salttype matrix. */
635 hierarchy[2] = KRB5_CONF_SUPPORTED_ENCTYPES;
636 if (params_in->mask & KADM5_CONFIG_ENCTYPES) {
637 if (params_in->keysalts) {
638 params.keysalts = copy_key_salt_tuple(params_in->keysalts,
639 params_in->num_keysalts);
640 if (params.keysalts) {
641 params.mask |= KADM5_CONFIG_ENCTYPES;
642 params.num_keysalts = params_in->num_keysalts;
643 }
644 } else {
645 params.mask |= KADM5_CONFIG_ENCTYPES;
646 params.keysalts = NULL;
647 params.num_keysalts = params_in->num_keysalts;
648 }
649 } else {
650 svalue = NULL;
651 if (aprofile != NULL)
652 krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);
653 if (svalue == NULL)
654 svalue = strdup(KRB5_DEFAULT_SUPPORTED_ENCTYPES);
655 if (svalue == NULL) {
656 ret = ENOMEM;
657 goto cleanup;
658 }
659
660 params.keysalts = NULL;
661 params.num_keysalts = 0;
662 krb5_string_to_keysalts(svalue,
663 NULL, /* Tuple separators */
664 NULL, /* Key/salt separators */
665 0, /* No duplicates */
666 ¶ms.keysalts,
667 ¶ms.num_keysalts);
668 if (params.num_keysalts)
669 params.mask |= KADM5_CONFIG_ENCTYPES;
670
671 free(svalue);
672 }
673
674 hierarchy[2] = KRB5_CONF_IPROP_ENABLE;
675
676 params.iprop_enabled = FALSE;
677 params.mask |= KADM5_CONFIG_IPROP_ENABLED;
678
679 if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) {
680 params.mask |= KADM5_CONFIG_IPROP_ENABLED;
681 params.iprop_enabled = params_in->iprop_enabled;
682 } else {
683 if (aprofile &&
684 !krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) {
685 params.iprop_enabled = bvalue;
686 params.mask |= KADM5_CONFIG_IPROP_ENABLED;
687 }
688 }
689
690 if (!GET_STRING_PARAM(iprop_logfile, KADM5_CONFIG_IPROP_LOGFILE,
691 KRB5_CONF_IPROP_LOGFILE, NULL)) {
692 if (params.mask & KADM5_CONFIG_DBNAME) {
693 if (asprintf(¶ms.iprop_logfile, "%s.ulog",
694 params.dbname) >= 0)
695 params.mask |= KADM5_CONFIG_IPROP_LOGFILE;
696 }
697 }
698
699 GET_PORT_PARAM(iprop_port, KADM5_CONFIG_IPROP_PORT, KRB5_CONF_IPROP_PORT,
700 0);
701
702 /* 5 min for large KDBs */
703 GET_DELTAT_PARAM(iprop_resync_timeout, KADM5_CONFIG_IPROP_RESYNC_TIMEOUT,
704 KRB5_CONF_IPROP_RESYNC_TIMEOUT, 60 * 5);
705
706 if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) {
707 params.mask |= KADM5_CONFIG_ULOG_SIZE;
708 params.iprop_ulogsize = params_in->iprop_ulogsize;
709 } else {
710 params.iprop_ulogsize = 0;
711 hierarchy[2] = KRB5_CONF_IPROP_ULOGSIZE;
712 if (aprofile != NULL &&
713 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) &&
714 ivalue > 0)
715 params.iprop_ulogsize = ivalue;
716 hierarchy[2] = KRB5_CONF_IPROP_MASTER_ULOGSIZE;
717 if (params.iprop_ulogsize == 0 && aprofile != NULL &&
718 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) &&
719 ivalue > 0)
720 params.iprop_ulogsize = ivalue;
721 if (params.iprop_ulogsize == 0)
722 params.iprop_ulogsize = DEF_ULOGENTRIES;
723 }
724 params.mask |= KADM5_CONFIG_ULOG_SIZE;
725
726 GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME,
727 KRB5_CONF_IPROP_REPLICA_POLL, -1);
728 if (params.iprop_poll_time == -1) {
729 GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME,
730 KRB5_CONF_IPROP_SLAVE_POLL, 2 * 60);
731 }
732
733 *params_out = params;
734
735 cleanup:
736 if (ret) {
737 kadm5_free_config_params(context, ¶ms);
738 params_out->mask = 0;
739 }
740 return ret;
741 }
742
743 /*
744 * kadm5_free_config_params() - Free data allocated by above.
745 */
746 krb5_error_code
kadm5_free_config_params(krb5_context context,kadm5_config_params * params)747 kadm5_free_config_params(krb5_context context, kadm5_config_params *params)
748 {
749 if (params == NULL)
750 return 0;
751 free(params->dbname);
752 free(params->mkey_name);
753 free(params->stash_file);
754 free(params->keysalts);
755 free(params->admin_server);
756 free(params->dict_file);
757 free(params->acl_file);
758 free(params->realm);
759 free(params->iprop_logfile);
760 return 0;
761 }
762
763 krb5_error_code
kadm5_get_admin_service_name(krb5_context ctx,char * realm_in,char * admin_name,size_t maxlen)764 kadm5_get_admin_service_name(krb5_context ctx, char *realm_in,
765 char *admin_name, size_t maxlen)
766 {
767 krb5_error_code ret;
768 kadm5_config_params params_in, params_out;
769 char *canonhost = NULL;
770
771 memset(¶ms_in, 0, sizeof(params_in));
772 memset(¶ms_out, 0, sizeof(params_out));
773
774 params_in.mask |= KADM5_CONFIG_REALM;
775 params_in.realm = realm_in;
776 ret = kadm5_get_config_params(ctx, 0, ¶ms_in, ¶ms_out);
777 if (ret)
778 return ret;
779
780 if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) {
781 ret = KADM5_MISSING_KRB5_CONF_PARAMS;
782 goto err_params;
783 }
784
785 ret = krb5_expand_hostname(ctx, params_out.admin_server, &canonhost);
786 if (ret)
787 goto err_params;
788
789 if (strlen(canonhost) + sizeof("kadmin/") > maxlen) {
790 ret = ENOMEM;
791 goto err_params;
792 }
793 snprintf(admin_name, maxlen, "kadmin/%s", canonhost);
794
795 err_params:
796 krb5_free_string(ctx, canonhost);
797 kadm5_free_config_params(ctx, ¶ms_out);
798 return ret;
799 }
800