4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
28 * Abstracted contract private interfaces for configuring krb5.conf(4).
36 __profile_iter_name_value(profile_t profile
, char *section
, char *key
,
39 const char *hierarchy
[4];
40 errcode_t code
, code2
;
41 char *name
= NULL
, *value
= NULL
, **ret_values
= NULL
;
43 struct profile_string_list values
;
44 boolean_t found
= FALSE
;
46 hierarchy
[0] = section
;
49 if (code
= init_list(&values
))
52 code
= profile_iterator_create(profile
, hierarchy
,
53 PROFILE_ITER_LIST_SECTION
, &state
);
55 code
= profile_iterator(&state
, &name
, &value
);
56 if (code
== 0 && name
!= NULL
) {
57 if ((key
== NULL
) || (strcmp(value
, key
) == 0)) {
58 code2
= add_to_list(&values
, name
);
60 end_list(&values
, &ret_values
);
61 profile_free_list(ret_values
);
69 profile_release_string(name
);
73 profile_release_string(value
);
79 end_list(&values
, &ret_values
);
84 profile_iterator_free(&state
);
86 profile_release_string(name
);
88 profile_release_string(value
);
90 *retvals
= ret_values
;
96 __profile_get_domain_realm(profile_t profile
, char *realm
, char ***domains
)
98 if (profile
== NULL
|| realm
== NULL
|| domains
== NULL
)
101 return (__profile_iter_name_value(profile
, "domain_realm", realm
,
106 __profile_set_appdefaults(profile_t profile
)
108 const char *hierarchy
[4];
114 hierarchy
[0] = "appdefaults";
115 hierarchy
[1] = "kinit";
118 hierarchy
[2] = "renewable";
121 * Not fatal if this fails, continue on.
123 (void) profile_clear_relation(profile
, hierarchy
);
125 code
= profile_add_relation(profile
, hierarchy
, "true");
129 hierarchy
[2] = "forwardable";
131 (void) profile_clear_relation(profile
, hierarchy
);
133 code
= profile_add_relation(profile
, hierarchy
, "true");
139 __profile_set_logging(profile_t profile
)
141 const char *hierarchy
[4];
147 hierarchy
[0] = "logging";
151 hierarchy
[1] = "default";
154 * Not fatal if this fails, continue on.
156 (void) profile_clear_relation(profile
, hierarchy
);
158 code
= profile_add_relation(profile
, hierarchy
,
159 "FILE:/var/krb5/kdc.log");
163 hierarchy
[1] = "kdc";
165 (void) profile_clear_relation(profile
, hierarchy
);
167 code
= profile_add_relation(profile
, hierarchy
,
168 "FILE:/var/krb5/kdc.log");
172 hierarchy
[1] = "kdc_rotate";
174 hierarchy
[2] = "period";
176 (void) profile_clear_relation(profile
, hierarchy
);
178 code
= profile_add_relation(profile
, hierarchy
, "1d");
182 hierarchy
[2] = "versions";
184 (void) profile_clear_relation(profile
, hierarchy
);
186 code
= profile_add_relation(profile
, hierarchy
, "10");
192 __profile_set_libdefaults(profile_t profile
, char *realm
)
194 const char *hierarchy
[4];
197 if (profile
== NULL
|| realm
== NULL
)
200 hierarchy
[0] = "libdefaults";
201 hierarchy
[1] = "default_realm";
205 * Not fatal if this fails, continue on.
207 (void) profile_clear_relation(profile
, hierarchy
);
209 code
= profile_add_relation(profile
, hierarchy
, realm
);
215 __profile_set_kdc(profile_t profile
, char *realm
, char *kdc
,
218 const char *hierarchy
[4];
221 if (profile
== NULL
|| realm
== NULL
|| kdc
== NULL
)
224 hierarchy
[0] = "realms";
225 hierarchy
[1] = realm
;
228 hierarchy
[2] = "kdc";
230 if (overwrite
== TRUE
) {
232 * Not fatal if this fails, continue on.
234 (void) profile_clear_relation(profile
, hierarchy
);
237 code
= profile_add_relation(profile
, hierarchy
, kdc
);
243 * errcode_t __profile_release(profile_t profile)
245 * where profile was the pointer passed back by __profile_init
246 * Note: used to commit the associated profile to the backing store
247 * (e.g. file) and free profile memory
248 * Note: that this function returns an error code which profile_release
249 * does not. With the error code, the application can determine if they
250 * need to free the resulting profile information in memory
253 __profile_release(profile_t profile
)
258 if (profile
== NULL
|| profile
->magic
!= PROF_MAGIC_PROFILE
)
261 for (p
= profile
->first_file
; p
; p
= next
) {
263 if ((code
= profile_close_file(p
)) != 0)
273 * void __profile_abandon(profile_t profile)
275 * where profile was the pointer passed back by __profile_init
276 * Note: used to free any profile information in memory. Typically can
277 * be used in conjunction with __profile_release upon error
280 __profile_abandon(profile_t profile
)
282 profile_abandon(profile
);
286 * errcode_t __profile_add_domain_mapping(profile_t profile, char *domain,
289 * where profile was the pointer passed back by __profile_init
290 * where domain is the domain name of the associated realm name
291 * where realm is the corresponding realm name for the domain
294 __profile_add_domain_mapping(profile_t profile
, char *domain
, char *realm
)
296 const char *hierarchy
[4];
299 if (profile
== NULL
|| domain
== NULL
|| realm
== NULL
)
302 hierarchy
[0] = "domain_realm";
303 hierarchy
[1] = domain
;
307 * Not fatal if relation can't be cleared, continue on.
309 (void) profile_clear_relation(profile
, hierarchy
);
311 code
= profile_add_relation(profile
, hierarchy
, realm
);
317 * errcode_t __profile_remove_domain_mapping(profile_t profile, char *realm)
319 * where profile was the pointer passed back by __profile_init
320 * where domain is the domain name of the associated realm name
321 * where realm is the corresponding realm name for the domain
322 * Note: for the remove function, all matching domain - realm mappings
323 * will be removed for realm
326 __profile_remove_domain_mapping(profile_t profile
, char *realm
)
328 const char *hierarchy
[4];
330 char **domains
= NULL
, **domain
= NULL
;
332 if (profile
== NULL
|| realm
== NULL
)
335 hierarchy
[0] = "domain_realm";
339 code
= __profile_get_domain_realm(profile
, realm
, &domains
);
340 if (code
== 0 && domains
!= NULL
) {
341 for (domain
= domains
; *domain
; domain
++) {
342 hierarchy
[1] = *domain
;
343 code
= profile_clear_relation(profile
, hierarchy
);
351 profile_free_list(domains
);
357 * errcode_t __profile_get_realm_entry(profile_t profile, char *realm,
358 * char *name, char ***ret_value)
360 * where profile was the pointer passed back by __profile_init
361 * where realm is the target realm for lookup
362 * where name is the name in the realm section requested
363 * where value is a string array of any matching values assigned to name.
364 * The array is terminated with a NULL pointer.
365 * Note: if no name has been configured and a profile does exist
366 * then value is set to NULL
369 __profile_get_realm_entry(profile_t profile
, char *realm
, char *name
,
372 const char *hierarchy
[4];
374 char **values
= NULL
;
376 if (profile
== NULL
|| realm
== NULL
|| name
== NULL
||
380 hierarchy
[0] = "realms";
381 hierarchy
[1] = realm
;
385 code
= profile_get_values(profile
, hierarchy
, &values
);
386 if (code
== 0 && values
!= NULL
)
389 if (code
== PROF_NO_RELATION
)
396 * errcode_t __profile_add_realm_entry(profile_t profile, char *realm,
397 * char *name, char **value)
399 * where profile was the pointer passed back by __profile_init
400 * where realm is the target realm for the name-value pair
401 * where name is the name in the realm subsection to add
402 * where value is a string array values to assigned to name. The array is
403 * terminated with a NULL pointer.
404 * Note: if the realm subsection does no exist then an error is returned
405 * Note: if the name already exists the set is overwritten with the values
409 __profile_add_realm_entry(profile_t profile
, char *realm
, char *name
,
412 const char *hierarchy
[4];
414 char **tvalue
= NULL
;
416 if (profile
== NULL
|| realm
== NULL
|| name
== NULL
|| values
== NULL
)
419 hierarchy
[0] = "realms";
420 hierarchy
[1] = realm
;
425 * Not fatal if this fails, continue on.
427 (void) profile_clear_relation(profile
, hierarchy
);
429 for (tvalue
= values
; *tvalue
; tvalue
++) {
431 code
= profile_add_relation(profile
, hierarchy
, *tvalue
);
440 * errcode_t __profile_get_default_realm(profile_t profile, char **realm)
442 * where profile was the pointer passed back by __profile_init
443 * where realm is the default_realm configured for the system
444 * Note: if no default_realm has been configured and a profile does exist
445 * then realm is set to NULL
448 __profile_get_default_realm(profile_t profile
, char **realm
)
453 if (profile
== NULL
|| realm
== NULL
)
456 code
= profile_get_string(profile
, "libdefaults", "default_realm", 0, 0,
458 if (code
== 0 && value
!= NULL
)
461 if (code
== PROF_NO_RELATION
)
468 * errcode_t __profile_get_realms(profile_t profile, char ***realms)
470 * where profile was the pointer passed back by __profile_init
471 * where realms is a string array of realm names currently configured.
472 * The array is terminated with a NULL pointer.
473 * Note: if no realms have been configured and a profile does exist then
474 * realms is set to NULL
477 __profile_get_realms(profile_t profile
, char ***realms
)
480 if (profile
== NULL
|| realms
== NULL
)
483 return (__profile_iter_name_value(profile
, "realms", NULL
, realms
));
487 * errcode_t __profile_add_realm(profile_t profile, char *realm,
488 * char *master, char **kdcs, boolean_t set_change, boolean_t
491 * where profile was the pointer passed back by __profile_init
492 * where realm is the realm name associated with the configuration
493 * where master is the server that is assigned to admin_server
494 * where kdcs is a string array of KDCs used to populate the kdc set.
495 * The array is terminated with a NULL pointer.
496 * where set_change, if set, will use the SET_CHANGE protocol for password
497 * modifications. RPCSEC_GSS is set by default
498 * where default_realm, if set, will assign the realm to default_realm
499 * Note: the ordering of kdcs is determined by the server's position in the
501 * Note: kdcs must be assigned a value, even if it is the same value as the
505 __profile_add_realm(profile_t profile
, char *realm
, char *master
, char **kdcs
,
506 boolean_t set_change
, boolean_t default_realm
)
508 const char *hierarchy
[4];
513 if (profile
== NULL
|| realm
== NULL
|| master
== NULL
|| kdcs
== NULL
)
517 * Sets the default realm to realm if default_realm flag is set.
519 if (default_realm
== TRUE
) {
520 if (code
= __profile_set_libdefaults(profile
, realm
))
524 hierarchy
[0] = "realms";
525 hierarchy
[1] = realm
;
528 hierarchy
[2] = "admin_server";
531 * Not fatal if this fails, therefore return code is not checked.
533 (void) profile_clear_relation(profile
, hierarchy
);
535 if (code
= profile_add_relation(profile
, hierarchy
, master
))
539 * If not set then defaults to undefined, which defaults to RPCSEC_GSS.
541 if (set_change
== TRUE
) {
542 hierarchy
[2] = "kpasswd_protocol";
544 (void) profile_clear_relation(profile
, hierarchy
);
546 code
= profile_add_relation(profile
, hierarchy
, "SET_CHANGE");
551 for (tkdcs
= kdcs
; *tkdcs
; tkdcs
++) {
552 if (code
= __profile_set_kdc(profile
, realm
, *tkdcs
, ow
))
557 code
= __profile_set_logging(profile
);
561 code
= __profile_set_appdefaults(profile
);
567 * errcode_t __profile_remove_xrealm_mapping(profile_t profile, char *realm)
569 * where profile was the pointer passed back by __profile_init
570 * where source is the source realm for the capath
571 * where target is the target realm for the capath
572 * where inter is the intermediate realm between the source and target
573 * realms. If the source and target share x-realm keys then this set to "."
574 * Note: for the remove function, all associated source, target, and
575 * intermediate entries will be removed matching the realm name
578 __profile_remove_xrealm_mapping(profile_t profile
, char *realm
)
580 const char *hierarchy
[4];
581 errcode_t code
, code2
, code3
;
582 void *state
= NULL
, *state2
= NULL
;
583 char *source
= NULL
, *dummy_val
= NULL
, *target
= NULL
;
586 if (profile
== NULL
|| realm
== NULL
)
589 hierarchy
[0] = "capaths";
590 hierarchy
[1] = realm
;
595 * Not fatal if this fails, continue on.
597 code
= profile_rename_section(profile
, hierarchy
, NULL
);
600 code
= profile_iterator_create(profile
, hierarchy
,
601 PROFILE_ITER_LIST_SECTION
, &state
);
603 code
= profile_iterator(&state
, &source
, &dummy_val
);
604 if (code
== 0 && source
!= NULL
) {
605 hierarchy
[1] = source
;
606 code2
= profile_iterator_create(profile
, hierarchy
,
607 PROFILE_ITER_LIST_SECTION
, &state2
);
609 code2
= profile_iterator(&state2
, &target
,
611 if (code2
== 0 && target
!= NULL
&&
613 if (strcmp(realm
, target
) == 0 ||
614 strcmp(realm
, inter
) == 0) {
615 hierarchy
[2] = target
;
617 profile_clear_relation(
625 if (target
!= NULL
) {
626 profile_release_string(target
);
630 profile_release_string(inter
);
635 if (source
!= NULL
) {
636 profile_release_string(source
);
639 if (dummy_val
!= NULL
) {
640 profile_release_string(dummy_val
);
648 profile_iterator_free(&state
);
650 profile_iterator_free(&state2
);
652 profile_release_string(target
);
654 profile_release_string(inter
);
656 profile_release_string(source
);
657 if (dummy_val
!= NULL
)
658 profile_release_string(dummy_val
);
664 * errcode_t __profile_remove_realm(profile_t profile, char *realm)
666 * where profile was the pointer passed back by __profile_init
667 * where realm is the target realm for removal
668 * Note: the function removes the matching realm in the realms section,
669 * the default_realm, relevant domain_realm mappings with the realm name,
670 * and matching capaths source realm subsection.
673 __profile_remove_realm(profile_t profile
, char *realm
)
675 const char *hierarchy
[4];
679 if (profile
== NULL
|| realm
== NULL
)
683 * Remove the default realm.
685 hierarchy
[0] = "libdefaults";
686 hierarchy
[1] = "default_realm";
689 code
= __profile_get_default_realm(profile
, &drealm
);
692 else if (drealm
!= NULL
) {
693 if (strcmp(drealm
, realm
) == 0) {
694 code
= profile_clear_relation(profile
, hierarchy
);
703 hierarchy
[0] = "realms";
704 hierarchy
[1] = realm
;
707 code
= profile_rename_section(profile
, hierarchy
, NULL
);
711 code
= __profile_remove_domain_mapping(profile
, realm
);
715 code
= __profile_remove_xrealm_mapping(profile
, realm
);
720 * Not fatal even if realm wasn't available to remove.
726 * errcode_t __profile_add_xrealm_mapping(profile_t profile, char *source,
727 * char *target, char *inter)
729 * where profile was the pointer passed back by __profile_init
730 * where source is the source realm for the capath
731 * where target is the target realm for the capath
732 * where inter is the intermediate realm between the source and target
733 * realms. If the source and target share x-realm keys then this set to "."
734 * Note: if the section does not exist one will be created
737 __profile_add_xrealm_mapping(profile_t profile
, char *source
, char *target
,
740 const char *hierarchy
[4];
743 if (profile
== NULL
|| source
== NULL
|| target
== NULL
||
747 hierarchy
[0] = "capaths";
748 hierarchy
[1] = source
;
749 hierarchy
[2] = target
;
753 * Not fatal if this fails, continue on.
755 (void) profile_clear_relation(profile
, hierarchy
);
757 code
= profile_add_relation(profile
, hierarchy
, inter
);
763 * errcode_t __profile_validate(profile_t profile, int *val_err, char **val)
765 * where profile was the pointer passed back by __profile_init
766 * where val_err is a function specific error code of the following values:
767 * 0 No errors detected in profile
768 * 1 default realm is in lower-case (val returns realm)
769 * 2 realm in realms section is in lower-case (val returns realm)
770 * 3 default realm is not found in realms section
771 * (val returns realm not found)
772 * 4 default realm does not exist
773 * 5 no realm found in realms section
774 * 6 no domain realm mapping entry found corresponding to a realm
775 * in the realms section (val returns realm name)
776 * 7 kdc relation-value does not exist in realm
777 * (val returns realm name)
778 * 8 admin_server relation-value does not exist in realm
779 * (val returns realm name)
780 * where val is the associated errant value, associated with val_err. This
781 * value is returned as is from the profile
782 * Note: function infers the following:
783 * 1. REALM should be in upper-case
784 * 2. all required entries are present
785 * 3. all relations are defined between default realm, realm, and
786 * domain - realm mappings
788 * Note: The return value of this function is based on the error code returned
789 * by the framework/mechanism. The function could return zero with the
790 * validation error code set to non-zero if the profile is invalid in any way.
792 * Caution: This function could return false positives on valid
793 * configurations and should only be used by the CIFS team for
797 __profile_validate(profile_t profile
, int *val_err
, char **val
)
801 boolean_t found
= FALSE
;
802 char *default_realm
= NULL
, **realms
= NULL
, *tr
= NULL
;
803 char **trealms
= NULL
, **domains
= NULL
, **ret_vals
= NULL
;
805 if (profile
== NULL
|| val_err
== NULL
|| val
== NULL
)
811 code
= __profile_get_default_realm(profile
, &default_realm
);
812 if (code
== 0 && default_realm
!= NULL
) {
815 while ((c
= *tr
++) != NULL
) {
818 *val
= strdup(default_realm
);
824 } else if (code
== 0 && default_realm
== NULL
) {
830 code
= __profile_get_realms(profile
, &realms
);
831 if (code
== 0 && realms
!= NULL
) {
832 for (trealms
= realms
; *trealms
; trealms
++) {
835 while ((c
= *tr
++) != NULL
) {
838 *val
= strdup(*trealms
);
845 if (strcmp(default_realm
, *trealms
) == 0)
848 code
= __profile_get_domain_realm(profile
, *trealms
,
850 if (code
== 0 && domains
!= NULL
) {
851 profile_free_list(domains
);
853 } else if (code
== 0 && domains
== NULL
) {
855 *val
= strdup(*trealms
);
862 code
= __profile_get_realm_entry(profile
, *trealms
,
864 if (code
== 0 && ret_vals
!= NULL
) {
865 profile_free_list(ret_vals
);
867 } else if (code
== 0 && ret_vals
== NULL
) {
869 *val
= strdup(*trealms
);
876 code
= __profile_get_realm_entry(profile
, *trealms
,
877 "admin_server", &ret_vals
);
878 if (code
== 0 && ret_vals
!= NULL
) {
879 profile_free_list(ret_vals
);
881 } else if (code
== 0 && ret_vals
== NULL
) {
883 *val
= strdup(*trealms
);
891 if (found
== FALSE
) {
893 *val
= strdup(default_realm
);
898 } else if (code
== 0 && realms
== NULL
)
904 profile_free_list(realms
);
905 if (ret_vals
!= NULL
)
906 profile_free_list(ret_vals
);
907 if (default_realm
!= NULL
)
908 profile_release_string(default_realm
);
910 profile_free_list(domains
);
916 * errcode_t __profile_init(char *filename, profile_t *profile)
918 * where filename is the specified profile location. If filename is NULL
919 * then function uses the system default name, /etc/krb5/krb5.conf
920 * where profile is pointer passed to caller upon success
921 * Note: if the file does not exist then one will be created
922 * Note: if the file does exist then any existing profile information will
924 * Note: profile_release() should be used by the caller to free profile
927 __profile_init(char *filename
, profile_t
*profile
)
929 profile_filespec_t
*filenames
= NULL
;
930 krb5_error_code ret
= 0;
933 mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
;
938 if (filename
!= NULL
) {
939 filenames
= malloc(2 * sizeof (char *));
940 if (filenames
== NULL
)
942 filenames
[0] = strdup(filename
);
943 if (filenames
[0] == NULL
) {
949 ret
= krb5_get_default_config_files(&filenames
);
955 * If file does not exist then create said file.
957 fd
= open(*filenames
, O_RDWR
|O_CREAT
|O_NOFOLLOW
|O_NOLINKS
, mode
);
960 krb5_free_config_files(filenames
);
966 * Specify non-null for specific file (to load any existing profile)
968 code
= profile_init((const_profile_filespec_t
*)filenames
, profile
);
970 krb5_free_config_files(filenames
);