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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
34 #include <sys/types.h>
37 #include "cryptoadm.h"
39 static int err
; /* To store errno which may be overwritten by gettext() */
40 static int build_entrylist(entry_t
*pent
, entrylist_t
**pplist
);
41 static entry_t
*dup_entry(entry_t
*pent1
);
42 static mechlist_t
*dup_mechlist(mechlist_t
*plist
);
43 static entry_t
*getent(char *provname
, entrylist_t
*entrylist
);
44 static int interpret(char *buf
, entry_t
**ppent
);
45 static int parse_sup_dis_list(const char *buf
, entry_t
*pent
);
49 * Duplicate the mechanism list. A null pointer is returned if the storage
50 * space available is insufficient or the input argument is NULL.
53 dup_mechlist(mechlist_t
*plist
)
55 mechlist_t
*pres
= NULL
;
60 while (plist
!= NULL
) {
61 if (!(ptmp
= create_mech(plist
->name
))) {
85 * Get the number of mechanisms in the mechanism list.
88 get_mech_count(mechlist_t
*plist
)
92 while (plist
!= NULL
) {
100 * Create one item of type entry_t with the provider name.
101 * Return NULL if there's not enough memory or provname is NULL.
104 create_entry(char *provname
)
106 entry_t
*pent
= NULL
;
108 if (provname
== NULL
) {
112 pent
= calloc(1, sizeof (entry_t
));
114 cryptodebug("out of memory.");
118 (void) strlcpy(pent
->name
, provname
, MAXNAMELEN
);
119 pent
->suplist
= NULL
;
121 pent
->dislist
= NULL
;
129 * Duplicate an entry for a provider from kcf.conf.
130 * Return NULL if memory is insufficient or the input argument is NULL.
131 * Called by getent().
134 dup_entry(entry_t
*pent1
)
136 entry_t
*pent2
= NULL
;
142 if ((pent2
= create_entry(pent1
->name
)) == NULL
) {
143 cryptodebug("out of memory.");
147 pent2
->sup_count
= pent1
->sup_count
;
148 pent2
->dis_count
= pent1
->dis_count
;
149 pent2
->load
= pent1
->load
;
150 if (pent1
->suplist
!= NULL
) {
151 pent2
->suplist
= dup_mechlist(pent1
->suplist
);
152 if (pent2
->suplist
== NULL
) {
157 if (pent1
->dislist
!= NULL
) {
158 pent2
->dislist
= dup_mechlist(pent1
->dislist
);
159 if (pent2
->dislist
== NULL
) {
170 * This routine parses the disabledlist or the supportedlist of an entry
171 * in the kcf.conf configuration file.
174 * buf: an input argument which is a char string with the format of
175 * "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
176 * pent: the entry for the disabledlist. This is an IN/OUT argument.
178 * Return value: SUCCESS or FAILURE.
181 parse_sup_dis_list(const char *buf
, entry_t
*pent
)
183 mechlist_t
*pmech
= NULL
;
184 mechlist_t
*phead
= NULL
;
188 int supflag
= B_FALSE
;
189 int disflag
= B_FALSE
;
192 if (strncmp(buf
, EF_SUPPORTED
, strlen(EF_SUPPORTED
)) == 0) {
194 } else if (strncmp(buf
, EF_DISABLED
, strlen(EF_DISABLED
)) == 0) {
197 /* should not come here */
201 if (value
= strpbrk(buf
, SEP_EQUAL
)) {
202 value
++; /* get rid of = */
204 cryptodebug("failed to parse the kcf.conf file.");
208 if ((next_token
= strtok(value
, SEP_COMMA
)) == NULL
) {
209 cryptodebug("failed to parse the kcf.conf file.");
213 if ((pmech
= create_mech(next_token
)) == NULL
) {
218 if (pent
->suplist
!= NULL
) {
219 cryptodebug("multiple supportedlist entries "
220 "for a mechanism in file kcf.conf.");
223 pent
->suplist
= phead
= pmech
;
225 } else if (disflag
) {
226 if (pent
->dislist
!= NULL
) {
227 cryptodebug("multiple disabledlist entries "
228 "for a mechanism in file kcf.conf.");
231 pent
->dislist
= phead
= pmech
;
237 if (next_token
= strtok(NULL
, SEP_COMMA
)) {
238 if ((pmech
= create_mech(next_token
)) == NULL
) {
250 pent
->sup_count
= count
;
251 } else if (disflag
) {
252 pent
->dis_count
= count
;
255 free_mechlist(phead
);
263 * Convert a char string containing a line about a provider
264 * from kcf.conf into an entry_t structure.
266 * Note: the input string, buf, may be modified by this function.
268 * See ent2str(), the reverse of this function, for the format of
272 interpret(char *buf
, entry_t
**ppent
)
274 entry_t
*pent
= NULL
;
280 /* Get provider name */
281 if ((token1
= strtok(buf
, SEP_COLON
)) == NULL
) { /* buf is NULL */
285 pent
= create_entry(token1
);
287 cryptodebug("out of memory.");
291 if ((token2
= strtok(NULL
, SEP_SEMICOLON
)) == NULL
) {
292 /* The entry contains a provider name only */
297 if (strncmp(token2
, EF_UNLOAD
, strlen(EF_UNLOAD
)) == 0) {
298 pent
->load
= B_FALSE
; /* cryptoadm unload */
299 token2
= strtok(NULL
, SEP_SEMICOLON
);
301 * If token2 is NULL, the entry contains a
302 * provider name:unload only
306 if (token2
!= NULL
) {
308 * Either supportedlist or disabledlist or both are present.
309 * Need to call strtok() to get token3 first, as function
310 * parse_sup_dis_list() makes strtok() calls on the
313 token3
= strtok(NULL
, SEP_SEMICOLON
); /* optional */
315 /* parse supportedlist (or disabledlist if no supportedlist) */
316 if ((rc
= parse_sup_dis_list(token2
, pent
)) != SUCCESS
) {
321 /* parse disabledlist (if there's a supportedlist) */
322 if ((token3
!= NULL
) && ((rc
= parse_sup_dis_list(token3
,
323 pent
)) != SUCCESS
)) {
335 * Add an entry about a provider from kcf.conf to the end of an entry list.
336 * If the entry list pplist is NULL, create the linked list with pent as the
340 build_entrylist(entry_t
*pent
, entrylist_t
**pplist
)
342 entrylist_t
*pentlist
;
343 entrylist_t
*pcur
= NULL
;
345 pentlist
= malloc(sizeof (entrylist_t
));
346 if (pentlist
== NULL
) {
347 cryptodebug("out of memory.");
350 pentlist
->pent
= pent
;
351 pentlist
->next
= NULL
;
355 while (pcur
->next
!= NULL
)
357 pcur
->next
= pentlist
;
358 } else { /* empty list */
368 * Find the entry with the "provname" name from the entry list and duplicate
369 * it. Called by getent_kef().
372 getent(char *provname
, entrylist_t
*entrylist
)
374 boolean_t found
= B_FALSE
;
375 entry_t
*pent1
= NULL
;
377 if ((provname
== NULL
) || (entrylist
== NULL
)) {
381 while (!found
&& entrylist
) {
382 if (strcmp(entrylist
->pent
->name
, provname
) == 0) {
384 pent1
= entrylist
->pent
;
386 entrylist
= entrylist
->next
;
394 /* duplicate the entry to be returned */
395 return (dup_entry(pent1
));
400 * Free memory in entry_t.
401 * That is, the supported and disabled lists for a provider
405 free_entry(entry_t
*pent
)
410 free_mechlist(pent
->suplist
);
411 free_mechlist(pent
->dislist
);
418 * Free elements in a entrylist_t linked list,
419 * which lists providers in kcf.conf.
422 free_entrylist(entrylist_t
*entrylist
)
426 while (entrylist
!= NULL
) {
427 pnext
= entrylist
->next
;
428 free_entry(entrylist
->pent
);
435 * Convert an entry_t to a kcf.conf line string. Build a string to insert
436 * as a line in file kcf.conf. Based on the content of an entry_t,
437 * the result string is one of these 8 forms:
438 * - name:supportedlist=m1,m2,...,mj
439 * - name:disabledlist=m1,m2,...,mj
440 * - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
443 * - name:unload;supportedlist=m1,m2,...,mj
444 * - name:unload;disabledlist=m1,m2,...,mj
445 * - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
447 * - (NUL character or 0-length string)
449 * Return a 0-length empty string if no keyword is present (that is,
450 * supportedlist, disabledlist, or unload). A kcf.conf line with just the
451 * provider name with no keyword is invalid.
453 * Note that the caller is responsible for freeing the returned string
454 * (with free_entry()).
455 * See interpret() for the reverse of this function: converting a string
459 ent2str(entry_t
*pent
)
462 mechlist_t
*pcur
= NULL
;
463 boolean_t keyword_already_present
= B_FALSE
;
469 if ((buf
= malloc(BUFSIZ
)) == NULL
) {
473 /* convert the provider name */
474 if (strlcpy(buf
, pent
->name
, BUFSIZ
) >= BUFSIZ
) {
479 if (!pent
->load
) { /* add "unload" keyword */
480 if (strlcat(buf
, SEP_COLON
, BUFSIZ
) >= BUFSIZ
) {
485 if (strlcat(buf
, EF_UNLOAD
, BUFSIZ
) >= BUFSIZ
) {
490 keyword_already_present
= B_TRUE
;
493 /* convert the supported list if any */
494 pcur
= pent
->suplist
;
497 keyword_already_present
? SEP_SEMICOLON
: SEP_COLON
,
503 if (strlcat(buf
, EF_SUPPORTED
, BUFSIZ
) >= BUFSIZ
) {
508 while (pcur
!= NULL
) {
509 if (strlcat(buf
, pcur
->name
, BUFSIZ
) >= BUFSIZ
) {
516 if (strlcat(buf
, SEP_COMMA
, BUFSIZ
)
523 keyword_already_present
= B_TRUE
;
526 /* convert the disabled list if any */
527 pcur
= pent
->dislist
;
530 keyword_already_present
? SEP_SEMICOLON
: SEP_COLON
,
536 if (strlcat(buf
, EF_DISABLED
, BUFSIZ
) >= BUFSIZ
) {
541 while (pcur
!= NULL
) {
542 if (strlcat(buf
, pcur
->name
, BUFSIZ
) >= BUFSIZ
) {
549 if (strlcat(buf
, SEP_COMMA
, BUFSIZ
)
556 keyword_already_present
= B_TRUE
;
559 if (strlcat(buf
, "\n", BUFSIZ
) >= BUFSIZ
) {
564 if (!keyword_already_present
) {
565 /* Only the provider name, without a keyword, is on the line */
573 * Enable the mechanisms for the provider pointed by *ppent. If allflag is
574 * TRUE, enable all. Otherwise, enable the mechanisms specified in the 3rd
575 * argument "mlist". The result will be stored in ppent also.
578 enable_mechs(entry_t
**ppent
, boolean_t allflag
, mechlist_t
*mlist
)
581 mechlist_t
*phead
; /* the current and resulting disabled list */
582 mechlist_t
*ptr
= NULL
;
583 mechlist_t
*pcur
= NULL
;
592 free_mechlist(pent
->dislist
);
594 pent
->dislist
= NULL
;
599 * for each mechanism in the to-be-enabled mechanism list,
600 * - check if it is in the current disabled list
601 * - if found, delete it from the disabled list
602 * otherwise, give a warning.
605 while (ptr
!= NULL
) {
607 phead
= pcur
= pent
->dislist
;
608 while (!found
&& pcur
) {
609 if (strcmp(pcur
->name
, ptr
->name
) == 0) {
619 pent
->dislist
= pent
->dislist
->next
;
622 phead
->next
= pcur
->next
;
627 cryptoerror(LOG_STDERR
, gettext(
628 "(Warning) %1$s is either enabled already or not "
629 "a valid mechanism for %2$s"), ptr
->name
,
635 if (pent
->dis_count
== 0) {
636 pent
->dislist
= NULL
;
645 * Determine if the kernel provider name, path, is a device
646 * (that is, it contains a slash character (e.g., "mca/0").
647 * If so, it is a hardware provider; otherwise it is a software provider.
650 is_device(char *path
)
652 if (strchr(path
, SEP_SLASH
) != NULL
) {
660 * Split a hardware provider name with the "name/inst_num" format into
661 * a name and a number (e.g., split "mca/0" into "mca" instance 0).
664 split_hw_provname(char *provname
, char *pname
, int *inst_num
)
666 char name
[MAXNAMELEN
];
669 if (provname
== NULL
) {
673 (void) strlcpy(name
, provname
, MAXNAMELEN
);
674 if (strtok(name
, "/") == NULL
) {
678 if ((inst_str
= strtok(NULL
, "/")) == NULL
) {
682 (void) strlcpy(pname
, name
, MAXNAMELEN
);
683 *inst_num
= atoi(inst_str
);
690 * Retrieve information from kcf.conf and build a hardware device entry list
691 * and a software entry list of kernel crypto providers.
693 * This list is usually incomplete, as kernel crypto providers only have to
694 * be listed in kcf.conf if a mechanism is disabled (by cryptoadm) or
695 * if the kernel provider module is not one of the default kernel providers.
697 * The kcf.conf file is available only in the global zone.
700 get_kcfconf_info(entrylist_t
**ppdevlist
, entrylist_t
**ppsoftlist
)
705 entry_t
*pent
= NULL
;
708 if ((pfile
= fopen(_PATH_KCF_CONF
, "r")) == NULL
) {
709 cryptodebug("failed to open the kcf.conf file for read only");
715 while (fgets(buffer
, BUFSIZ
, pfile
) != NULL
) {
716 if (buffer
[0] == '#' || buffer
[0] == ' ' ||
717 buffer
[0] == '\n'|| buffer
[0] == '\t') {
718 continue; /* ignore comment lines */
721 len
= strlen(buffer
);
722 if (buffer
[len
- 1] == '\n') { /* get rid of trailing '\n' */
727 if ((rc
= interpret(buffer
, &pent
)) == SUCCESS
) {
728 if (is_device(pent
->name
)) {
729 rc
= build_entrylist(pent
, ppdevlist
);
731 rc
= build_entrylist(pent
, ppsoftlist
);
734 cryptoerror(LOG_STDERR
, gettext(
735 "failed to parse configuration."));
739 free_entrylist(*ppdevlist
);
740 free_entrylist(*ppsoftlist
);
746 (void) fclose(pfile
);
751 * Retrieve information from admin device and build a device entry list and
752 * a software entry list. This is used where there is no kcf.conf, e.g., the
756 get_admindev_info(entrylist_t
**ppdevlist
, entrylist_t
**ppsoftlist
)
758 crypto_get_dev_list_t
*pdevlist_kernel
= NULL
;
759 crypto_get_soft_list_t
*psoftlist_kernel
= NULL
;
763 mechlist_t
*pmech
= NULL
;
764 entry_t
*pent_dev
= NULL
, *pent_soft
= NULL
;
767 entrylist_t
*tmp_pdev
= NULL
;
768 entrylist_t
*tmp_psoft
= NULL
;
769 entrylist_t
*phardlist
= NULL
, *psoftlist
= NULL
;
772 * Get hardware providers
774 if (get_dev_list(&pdevlist_kernel
) != SUCCESS
) {
775 cryptodebug("failed to get hardware provider list from kernel");
779 for (i
= 0; i
< pdevlist_kernel
->dl_dev_count
; i
++) {
780 devname
= pdevlist_kernel
->dl_devs
[i
].le_dev_name
;
781 inst_num
= pdevlist_kernel
->dl_devs
[i
].le_dev_instance
;
782 mcount
= pdevlist_kernel
->dl_devs
[i
].le_mechanism_count
;
785 if (get_dev_info(devname
, inst_num
, mcount
, &pmech
) !=
788 "failed to retrieve the mechanism list for %s/%d.",
793 if ((pent_dev
= create_entry(devname
)) == NULL
) {
794 cryptodebug("out of memory.");
795 free_mechlist(pmech
);
798 pent_dev
->suplist
= pmech
;
799 pent_dev
->sup_count
= mcount
;
801 if (build_entrylist(pent_dev
, &tmp_pdev
) != SUCCESS
) {
806 free(pdevlist_kernel
);
807 pdevlist_kernel
= NULL
;
810 * Get software providers
812 if (getzoneid() == GLOBAL_ZONEID
) {
813 if (get_kcfconf_info(&phardlist
, &psoftlist
) != SUCCESS
) {
818 if (get_soft_list(&psoftlist_kernel
) != SUCCESS
) {
819 cryptodebug("failed to get software provider list from kernel");
823 for (i
= 0, psoftname
= psoftlist_kernel
->sl_soft_names
;
824 i
< psoftlist_kernel
->sl_soft_count
;
825 i
++, psoftname
= psoftname
+ strlen(psoftname
) + 1) {
827 if (get_soft_info(psoftname
, &pmech
, phardlist
, psoftlist
) !=
830 "failed to retrieve the mechanism list for %s.",
835 if ((pent_soft
= create_entry(psoftname
)) == NULL
) {
836 cryptodebug("out of memory.");
837 free_mechlist(pmech
);
840 pent_soft
->suplist
= pmech
;
841 pent_soft
->sup_count
= get_mech_count(pmech
);
843 if (build_entrylist(pent_soft
, &tmp_psoft
) != SUCCESS
) {
848 free(psoftlist_kernel
);
849 psoftlist_kernel
= NULL
;
851 *ppdevlist
= tmp_pdev
;
852 *ppsoftlist
= tmp_psoft
;
857 if (pent_dev
!= NULL
)
858 free_entry(pent_dev
);
859 if (pent_soft
!= NULL
)
860 free_entry(pent_soft
);
862 free_entrylist(tmp_pdev
);
863 free_entrylist(tmp_psoft
);
865 if (pdevlist_kernel
!= NULL
)
866 free(pdevlist_kernel
);
867 if (psoftlist_kernel
!= NULL
)
868 free(psoftlist_kernel
);
874 * Return configuration information for a kernel provider from kcf.conf.
875 * For kernel software providers return a enabled list and disabled list.
876 * For kernel hardware providers return just a disabled list.
878 * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
879 * If NULL, this function calls get_kcfconf_info() internally.
882 getent_kef(char *provname
, entrylist_t
*phardlist
, entrylist_t
*psoftlist
)
884 entry_t
*pent
= NULL
;
885 boolean_t memory_allocated
= B_FALSE
;
887 if ((phardlist
== NULL
) || (psoftlist
== NULL
)) {
888 if (get_kcfconf_info(&phardlist
, &psoftlist
) != SUCCESS
) {
891 memory_allocated
= B_TRUE
;
894 if (is_device(provname
)) {
895 pent
= getent(provname
, phardlist
);
897 pent
= getent(provname
, psoftlist
);
900 if (memory_allocated
) {
901 free_entrylist(phardlist
);
902 free_entrylist(psoftlist
);
909 * Print out the provider name and the mechanism list.
912 print_mechlist(char *provname
, mechlist_t
*pmechlist
)
914 mechlist_t
*ptr
= NULL
;
916 if (provname
== NULL
) {
920 (void) printf("%s: ", provname
);
921 if (pmechlist
== NULL
) {
922 (void) printf(gettext("No mechanisms presented.\n"));
927 while (ptr
!= NULL
) {
928 (void) printf("%s", ptr
->name
);
940 * Update the kcf.conf file based on the update mode:
941 * - If update_mode is MODIFY_MODE, modify the entry with the same name.
942 * If not found, append a new entry to the kcf.conf file.
943 * - If update_mode is DELETE_MODE, delete the entry with the same name.
944 * - If update_mode is ADD_MODE, append a new entry to the kcf.conf file.
947 update_kcfconf(entry_t
*pent
, int update_mode
)
949 boolean_t add_it
= B_FALSE
;
950 boolean_t delete_it
= B_FALSE
;
951 boolean_t this_entry_matches
= B_FALSE
;
952 boolean_t found_entry
= B_FALSE
;
954 FILE *pfile_tmp
= NULL
;
956 char buffer2
[BUFSIZ
];
957 char tmpfile_name
[MAXPATHLEN
];
959 char *new_str
= NULL
;
963 cryptoerror(LOG_STDERR
, gettext("internal error."));
967 /* Check the update_mode */
968 switch (update_mode
) {
973 /* Convert the entry a string to add to kcf.conf */
974 if ((new_str
= ent2str(pent
)) == NULL
) {
977 if (strlen(new_str
) == 0) {
986 cryptoerror(LOG_STDERR
, gettext("internal error."));
990 /* Open the kcf.conf file */
991 if ((pfile
= fopen(_PATH_KCF_CONF
, "r+")) == NULL
) {
993 cryptoerror(LOG_STDERR
,
994 gettext("failed to update the configuration - %s"),
996 cryptodebug("failed to open %s for write.", _PATH_KCF_CONF
);
1000 /* Lock the kcf.conf file */
1001 if (lockf(fileno(pfile
), F_TLOCK
, 0) == -1) {
1003 cryptoerror(LOG_STDERR
,
1004 gettext("failed to update the configuration - %s"),
1006 (void) fclose(pfile
);
1011 * Create a temporary file in the /etc/crypto directory to save
1012 * updated configuration file first.
1014 (void) strlcpy(tmpfile_name
, TMPFILE_TEMPLATE
, sizeof (tmpfile_name
));
1015 if (mkstemp(tmpfile_name
) == -1) {
1017 cryptoerror(LOG_STDERR
,
1018 gettext("failed to create a temporary file - %s"),
1020 (void) fclose(pfile
);
1024 if ((pfile_tmp
= fopen(tmpfile_name
, "w")) == NULL
) {
1026 cryptoerror(LOG_STDERR
, gettext("failed to open %s - %s"),
1027 tmpfile_name
, strerror(err
));
1028 (void) fclose(pfile
);
1033 * Loop thru the entire kcf.conf file, insert, modify or delete
1036 while (fgets(buffer
, BUFSIZ
, pfile
) != NULL
) {
1038 if (fputs(buffer
, pfile_tmp
) == EOF
) {
1040 cryptoerror(LOG_STDERR
, gettext(
1041 "failed to write to a temp file: %s."),
1047 } else { /* modify or delete */
1048 this_entry_matches
= B_FALSE
;
1050 if (!(buffer
[0] == '#' || buffer
[0] == ' ' ||
1051 buffer
[0] == '\n'|| buffer
[0] == '\t')) {
1053 * Get the provider name from this line and
1054 * check if this is the entry to be updated
1055 * or deleted. Note: can not use "buffer"
1056 * directly because strtok will change its
1059 (void) strlcpy(buffer2
, buffer
, BUFSIZ
);
1060 if ((name
= strtok(buffer2
, SEP_COLON
)) ==
1066 if (strcmp(pent
->name
, name
) == 0) {
1067 this_entry_matches
= B_TRUE
;
1068 found_entry
= B_TRUE
;
1073 if (!this_entry_matches
|| !delete_it
) {
1074 /* write this entry */
1075 if (this_entry_matches
) {
1077 * Modify this entry: get the
1078 * updated string and place into buffer.
1080 (void) strlcpy(buffer
, new_str
, BUFSIZ
);
1083 /* write the (unchanged or modified) entry */
1084 if (fputs(buffer
, pfile_tmp
) == EOF
) {
1086 cryptoerror(LOG_STDERR
, gettext(
1087 "failed to write to a temp file: "
1088 "%s."), strerror(err
));
1096 if ((!delete_it
) && (rc
!= FAILURE
)) {
1097 if (add_it
|| !found_entry
) {
1098 /* append new entry to end of file */
1099 if (fputs(new_str
, pfile_tmp
) == EOF
) {
1101 cryptoerror(LOG_STDERR
, gettext(
1102 "failed to write to a temp file: %s."),
1110 (void) fclose(pfile
);
1111 if (fclose(pfile_tmp
) != 0) {
1113 cryptoerror(LOG_STDERR
,
1114 gettext("failed to close %s: %s"), tmpfile_name
,
1119 /* Copy the temporary file to the kcf.conf file */
1120 if (rename(tmpfile_name
, _PATH_KCF_CONF
) == -1) {
1122 cryptoerror(LOG_STDERR
,
1123 gettext("failed to update the configuration - %s"),
1125 cryptodebug("failed to rename %s to %s: %s", tmpfile
,
1126 _PATH_KCF_CONF
, strerror(err
));
1128 } else if (chmod(_PATH_KCF_CONF
,
1129 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
) == -1) {
1131 cryptoerror(LOG_STDERR
,
1132 gettext("failed to update the configuration - %s"),
1134 cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF
,
1141 if ((rc
== FAILURE
) && (unlink(tmpfile_name
) != 0)) {
1143 cryptoerror(LOG_STDERR
, gettext(
1144 "(Warning) failed to remove %s: %s"),
1145 tmpfile_name
, strerror(err
));
1153 * Disable the mechanisms for the provider pointed by *ppent. If allflag is
1154 * TRUE, disable all. Otherwise, disable the mechanisms specified in the
1155 * dislist argument. The "infolist" argument contains the mechanism list
1156 * supported by this provider.
1159 disable_mechs(entry_t
**ppent
, mechlist_t
*infolist
, boolean_t allflag
,
1160 mechlist_t
*dislist
)
1163 mechlist_t
*plist
= NULL
;
1164 mechlist_t
*phead
= NULL
;
1165 mechlist_t
*pmech
= NULL
;
1174 free_mechlist(pent
->dislist
);
1175 pent
->dis_count
= get_mech_count(infolist
);
1176 if (!(pent
->dislist
= dup_mechlist(infolist
))) {
1184 * Not disable all. Now loop thru the mechanisms specified in the
1185 * dislist. If the mechanism is not supported by the provider,
1186 * ignore it with a warning. If the mechanism is disabled already,
1187 * do nothing. Otherwise, prepend it to the beginning of the disabled
1188 * list of the provider.
1191 while (plist
!= NULL
) {
1192 if (!is_in_list(plist
->name
, infolist
)) {
1193 cryptoerror(LOG_STDERR
, gettext("(Warning) "
1194 "%1$s is not a valid mechanism for %2$s."),
1195 plist
->name
, pent
->name
);
1196 } else if (!is_in_list(plist
->name
, pent
->dislist
)) {
1197 /* Add this mechanism into the disabled list */
1198 if ((pmech
= create_mech(plist
->name
)) == NULL
) {
1203 if (pent
->dislist
== NULL
) {
1204 pent
->dislist
= pmech
;
1206 phead
= pent
->dislist
;
1207 pent
->dislist
= pmech
;
1208 pmech
->next
= phead
;
1212 plist
= plist
->next
;
1219 * Remove the mechanism passed, specified by mech, from the list of
1220 * mechanisms, if present in the list. Else, do nothing.
1222 * Returns B_TRUE if mechanism is present in the list.
1225 filter_mechlist(mechlist_t
**pmechlist
, const char *mech
)
1228 mechlist_t
*ptr
, *pptr
;
1229 boolean_t mech_present
= B_FALSE
;
1231 ptr
= pptr
= *pmechlist
;
1233 while (ptr
!= NULL
) {
1234 if (strncmp(ptr
->name
, mech
, sizeof (mech_name_t
)) == 0) {
1235 mech_present
= B_TRUE
;
1236 if (ptr
== *pmechlist
) {
1237 pptr
= *pmechlist
= ptr
->next
;
1241 pptr
->next
= ptr
->next
;
1252 /* Only one entry is present */
1256 return (mech_present
);
1262 * Print out the mechanism policy for a kernel provider that has an entry
1263 * in the kcf.conf file.
1265 * The flag has_random is set to B_TRUE if the provider does random
1266 * numbers. The flag has_mechs is set by the caller to B_TRUE if the provider
1267 * has some mechanisms.
1269 * If pent is NULL, the provider doesn't have a kcf.conf entry.
1272 print_kef_policy(char *provname
, entry_t
*pent
, boolean_t has_random
,
1273 boolean_t has_mechs
)
1275 mechlist_t
*ptr
= NULL
;
1276 boolean_t rnd_disabled
= B_FALSE
;
1279 rnd_disabled
= filter_mechlist(&pent
->dislist
, RANDOM
);
1280 ptr
= pent
->dislist
;
1283 (void) printf("%s:", provname
);
1285 if (has_mechs
== B_TRUE
) {
1288 * This code block may need to be modified a bit to avoid
1289 * constructing the text message on the fly.
1291 (void) printf(gettext(" all mechanisms are enabled"));
1293 (void) printf(gettext(", except "));
1294 while (ptr
!= NULL
) {
1295 (void) printf("%s", ptr
->name
);
1306 * "random" is a keyword and not to be translated.
1309 (void) printf(gettext(" %s is disabled."), "random");
1310 else if (has_random
)
1311 (void) printf(gettext(" %s is enabled."), "random");
1312 (void) printf("\n");
1317 * Check if a kernel software provider is in the kernel.
1320 * provname Provider name
1321 * psoftlist_kernel Optional software provider list. If NULL, it will be
1322 * obtained from get_soft_list().
1323 * in_kernel Set to B_TRUE if device is in the kernel, else B_FALSE
1326 check_kernel_for_soft(char *provname
, crypto_get_soft_list_t
*psoftlist_kernel
,
1327 boolean_t
*in_kernel
)
1331 boolean_t psoftlist_allocated
= B_FALSE
;
1333 if (provname
== NULL
) {
1334 cryptoerror(LOG_STDERR
, gettext("internal error."));
1338 if (psoftlist_kernel
== NULL
) {
1339 if (get_soft_list(&psoftlist_kernel
) == FAILURE
) {
1340 cryptodebug("failed to get the software provider list"
1344 psoftlist_allocated
= B_TRUE
;
1347 *in_kernel
= B_FALSE
;
1348 ptr
= psoftlist_kernel
->sl_soft_names
;
1349 for (i
= 0; i
< psoftlist_kernel
->sl_soft_count
; i
++) {
1350 if (strcmp(provname
, ptr
) == 0) {
1351 *in_kernel
= B_TRUE
;
1354 ptr
= ptr
+ strlen(ptr
) + 1;
1357 if (psoftlist_allocated
)
1358 free(psoftlist_kernel
);
1365 * Check if a kernel hardware provider is in the kernel.
1368 * provname Provider name
1369 * pdevlist Optional Hardware Crypto Device List. If NULL, it will be
1370 * obtained from get_dev_list().
1371 * in_kernel Set to B_TRUE if device is in the kernel, otherwise B_FALSE
1374 check_kernel_for_hard(char *provname
,
1375 crypto_get_dev_list_t
*pdevlist
, boolean_t
*in_kernel
)
1377 char devname
[MAXNAMELEN
];
1380 boolean_t dev_list_allocated
= B_FALSE
;
1382 if (provname
== NULL
) {
1383 cryptoerror(LOG_STDERR
, gettext("internal error."));
1387 if (split_hw_provname(provname
, devname
, &inst_num
) == FAILURE
) {
1391 if (pdevlist
== NULL
) {
1392 if (get_dev_list(&pdevlist
) == FAILURE
) {
1393 cryptoerror(LOG_STDERR
, gettext("internal error."));
1396 dev_list_allocated
= B_TRUE
;
1399 *in_kernel
= B_FALSE
;
1400 for (i
= 0; i
< pdevlist
->dl_dev_count
; i
++) {
1401 if ((strcmp(pdevlist
->dl_devs
[i
].le_dev_name
, devname
) == 0) &&
1402 (pdevlist
->dl_devs
[i
].le_dev_instance
== inst_num
)) {
1403 *in_kernel
= B_TRUE
;
1408 if (dev_list_allocated
)