/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <locale.h>
#include <zone.h>
#include "cryptoadm.h"
/*
* Duplicate the mechanism list. A null pointer is returned if the storage
* space available is insufficient or the input argument is NULL.
*/
static mechlist_t *
{
break;
}
} else {
}
}
return (NULL);
}
return (pres);
}
/*
* Get the number of mechanisms in the mechanism list.
*/
int
{
int count = 0;
count++;
}
return (count);
}
/*
* Create one item of type entry_t with the provider name.
* Return NULL if there's not enough memory or provname is NULL.
*/
entry_t *
{
return (NULL);
}
cryptodebug("out of memory.");
return (NULL);
}
return (pent);
}
/*
* Duplicate an entry for a provider from kcf.conf.
* Return NULL if memory is insufficient or the input argument is NULL.
* Called by getent().
*/
static entry_t *
{
return (NULL);
}
cryptodebug("out of memory.");
return (NULL);
}
return (NULL);
}
}
return (NULL);
}
}
return (pent2);
}
/*
* This routine parses the disabledlist or the supportedlist of an entry
* in the kcf.conf configuration file.
*
* Arguments:
* buf: an input argument which is a char string with the format of
* "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
*
* Return value: SUCCESS or FAILURE.
*/
static int
{
char *next_token;
char *value;
int count;
} else {
/* should not come here */
return (FAILURE);
}
value++; /* get rid of = */
} else {
cryptodebug("failed to parse the kcf.conf file.");
return (FAILURE);
}
cryptodebug("failed to parse the kcf.conf file.");
return (FAILURE);
}
return (FAILURE);
}
if (supflag) {
cryptodebug("multiple supportedlist entries "
"for a mechanism in file kcf.conf.");
return (FAILURE);
} else {
}
} else if (disflag) {
cryptodebug("multiple disabledlist entries "
"for a mechanism in file kcf.conf.");
return (FAILURE);
} else {
}
}
count = 1;
while (next_token) {
break;
}
count++;
}
}
if (supflag) {
} else if (disflag) {
}
} else {
}
return (rc);
}
/*
* Convert a char string containing a line about a provider
* from kcf.conf into an entry_t structure.
*
* Note: the input string, buf, may be modified by this function.
*
* See ent2str(), the reverse of this function, for the format of
* kcf.conf lines.
*/
static int
{
char *token1;
char *token2;
char *token3;
int rc;
/* Get provider name */
return (FAILURE);
};
cryptodebug("out of memory.");
return (FAILURE);
}
/* The entry contains a provider name only */
return (FAILURE);
}
/*
* If token2 is NULL, the entry contains a
* provider name:unload only
*/
}
/*
* Either supportedlist or disabledlist or both are present.
* Need to call strtok() to get token3 first, as function
* parse_sup_dis_list() makes strtok() calls on the
* token2 substring.
*/
/* parse supportedlist (or disabledlist if no supportedlist) */
return (rc);
}
/* parse disabledlist (if there's a supportedlist) */
return (rc);
}
}
return (SUCCESS);
}
/*
* Add an entry about a provider from kcf.conf to the end of an entry list.
* If the entry list pplist is NULL, create the linked list with pent as the
* first element.
*/
static int
{
cryptodebug("out of memory.");
return (FAILURE);
}
if (*pplist) {
} else { /* empty list */
}
return (SUCCESS);
}
/*
* Find the entry with the "provname" name from the entry list and duplicate
* it. Called by getent_kef().
*/
static entry_t *
{
return (NULL);
}
} else {
}
}
if (!found) {
return (NULL);
}
/* duplicate the entry to be returned */
}
/*
* Free memory in entry_t.
* That is, the supported and disabled lists for a provider
* from kcf.conf.
*/
void
{
return;
} else {
}
}
/*
* Free elements in a entrylist_t linked list,
* which lists providers in kcf.conf.
*/
void
{
}
}
/*
* Convert an entry_t to a kcf.conf line string. Build a string to insert
* as a line in file kcf.conf. Based on the content of an entry_t,
* the result string is one of these 8 forms:
* - name:supportedlist=m1,m2,...,mj
* - name:disabledlist=m1,m2,...,mj
* - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
*
* - name:unload
* - name:unload;supportedlist=m1,m2,...,mj
* - name:unload;disabledlist=m1,m2,...,mj
* - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
*
* - (NUL character or 0-length string)
*
* Return a 0-length empty string if no keyword is present (that is,
* supportedlist, disabledlist, or unload). A kcf.conf line with just the
* provider name with no keyword is invalid.
*
* Note that the caller is responsible for freeing the returned string
* (with free_entry()).
* See interpret() for the reverse of this function: converting a string
* to an entry_t.
*/
char *
{
char *buf;
return (NULL);
}
return (NULL);
}
/* convert the provider name */
return (NULL);
}
return (NULL);
}
return (NULL);
}
}
/* convert the supported list if any */
return (NULL);
}
return (NULL);
}
return (NULL);
}
>= BUFSIZ) {
return (NULL);
}
}
}
}
/* convert the disabled list if any */
return (NULL);
}
return (NULL);
}
return (NULL);
}
>= BUFSIZ) {
return (NULL);
}
}
}
}
return (NULL);
}
if (!keyword_already_present) {
/* Only the provider name, without a keyword, is on the line */
buf[0] = '\0';
}
return (buf);
}
/*
* Enable the mechanisms for the provider pointed by *ppent. If allflag is
* TRUE, enable all. Otherwise, enable the mechanisms specified in the 3rd
* argument "mlist". The result will be stored in ppent also.
*/
int
{
return (FAILURE);
}
if (allflag) {
return (SUCCESS);
}
/*
* for each mechanism in the to-be-enabled mechanism list,
* - check if it is in the current disabled list
* - if found, delete it from the disabled list
* otherwise, give a warning.
*/
} else {
}
}
if (found) {
} else {
}
} else {
"(Warning) %1$s is either enabled already or not "
}
}
}
return (SUCCESS);
}
/*
* Determine if the kernel provider name, path, is a device
* (that is, it contains a slash character (e.g., "mca/0").
* If so, it is a hardware provider; otherwise it is a software provider.
*/
{
return (B_TRUE);
} else {
return (B_FALSE);
}
}
/*
* a name and a number (e.g., split "mca/0" into "mca" instance 0).
*/
int
{
char *inst_str;
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
return (SUCCESS);
}
/*
* Retrieve information from kcf.conf and build a hardware device entry list
* and a software entry list of kernel crypto providers.
*
* This list is usually incomplete, as kernel crypto providers only have to
* be listed in kcf.conf if a mechanism is disabled (by cryptoadm) or
* if the kernel provider module is not one of the default kernel providers.
*
* The kcf.conf file is available only in the global zone.
*/
int
{
int len;
cryptodebug("failed to open the kcf.conf file for read only");
return (FAILURE);
}
*ppsoftlist = NULL;
continue; /* ignore comment lines */
}
len--;
}
} else {
}
} else {
"failed to parse configuration."));
}
break;
}
}
return (rc);
}
/*
* Retrieve information from admin device and build a device entry list and
* a software entry list. This is used where there is no kcf.conf, e.g., the
* non-global zone.
*/
int
{
char *devname;
int inst_num;
int mcount;
int i;
char *psoftname;
/*
* Get hardware providers
*/
cryptodebug("failed to get hardware provider list from kernel");
return (FAILURE);
}
for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
SUCCESS) {
"failed to retrieve the mechanism list for %s/%d.",
goto fail_out;
}
cryptodebug("out of memory.");
goto fail_out;
}
goto fail_out;
}
}
/*
* Get software providers
*/
if (getzoneid() == GLOBAL_ZONEID) {
goto fail_out;
}
}
cryptodebug("failed to get software provider list from kernel");
goto fail_out;
}
SUCCESS) {
"failed to retrieve the mechanism list for %s.",
goto fail_out;
}
cryptodebug("out of memory.");
goto fail_out;
}
goto fail_out;
}
}
*ppsoftlist = tmp_psoft;
return (SUCCESS);
if (pdevlist_kernel != NULL)
if (psoftlist_kernel != NULL)
return (FAILURE);
}
/*
* Return configuration information for a kernel provider from kcf.conf.
* For kernel software providers return a enabled list and disabled list.
* For kernel hardware providers return just a disabled list.
*
* Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
* If NULL, this function calls get_kcfconf_info() internally.
*/
entry_t *
{
return (NULL);
}
}
} else {
}
if (memory_allocated) {
}
return (pent);
}
/*
* Print out the provider name and the mechanism list.
*/
void
{
return;
}
return;
}
(void) printf("\n");
} else {
(void) printf(",");
}
}
}
/*
* Update the kcf.conf file based on the update mode:
* - If update_mode is MODIFY_MODE, modify the entry with the same name.
* If not found, append a new entry to the kcf.conf file.
* - If update_mode is DELETE_MODE, delete the entry with the same name.
* - If update_mode is ADD_MODE, append a new entry to the kcf.conf file.
*/
int
{
char *name;
return (FAILURE);
}
/* Check the update_mode */
switch (update_mode) {
case ADD_MODE:
/* FALLTHROUGH */
case MODIFY_MODE:
/* Convert the entry a string to add to kcf.conf */
return (FAILURE);
}
}
break;
case DELETE_MODE:
break;
default:
return (FAILURE);
}
/* Open the kcf.conf file */
gettext("failed to update the configuration - %s"),
return (FAILURE);
}
/* Lock the kcf.conf file */
gettext("failed to update the configuration - %s"),
return (FAILURE);
}
/*
* updated configuration file first.
*/
gettext("failed to create a temporary file - %s"),
return (FAILURE);
}
return (FAILURE);
}
/*
* Loop thru the entire kcf.conf file, insert, modify or delete
* an entry.
*/
if (add_it) {
"failed to write to a temp file: %s."),
break;
}
} else { /* modify or delete */
/*
* Get the provider name from this line and
* check if this is the entry to be updated
* or deleted. Note: can not use "buffer"
* directly because strtok will change its
* value.
*/
NULL) {
break;
}
}
}
if (!this_entry_matches || !delete_it) {
/* write this entry */
if (this_entry_matches) {
/*
* Modify this entry: get the
* updated string and place into buffer.
*/
}
/* write the (unchanged or modified) entry */
"failed to write to a temp file: "
break;
}
}
}
}
if (add_it || !found_entry) {
/* append new entry to end of file */
"failed to write to a temp file: %s."),
}
}
}
return (FAILURE);
}
/* Copy the temporary file to the kcf.conf file */
gettext("failed to update the configuration - %s"),
} else if (chmod(_PATH_KCF_CONF,
gettext("failed to update the configuration - %s"),
} else {
}
"(Warning) failed to remove %s: %s"),
}
return (rc);
}
/*
* Disable the mechanisms for the provider pointed by *ppent. If allflag is
* TRUE, disable all. Otherwise, disable the mechanisms specified in the
* dislist argument. The "infolist" argument contains the mechanism list
* supported by this provider.
*/
int
{
return (FAILURE);
}
if (allflag) {
return (FAILURE);
} else {
return (SUCCESS);
}
}
/*
* Not disable all. Now loop thru the mechanisms specified in the
* dislist. If the mechanism is not supported by the provider,
* ignore it with a warning. If the mechanism is disabled already,
* do nothing. Otherwise, prepend it to the beginning of the disabled
* list of the provider.
*/
"%1$s is not a valid mechanism for %2$s."),
/* Add this mechanism into the disabled list */
break;
}
} else {
}
}
}
return (rc);
}
/*
* Remove the mechanism passed, specified by mech, from the list of
* mechanisms, if present in the list. Else, do nothing.
*
* Returns B_TRUE if mechanism is present in the list.
*/
{
int cnt = 0;
} else {
}
} else {
cnt++;
}
}
/* Only one entry is present */
if (cnt == 0)
return (mech_present);
}
/*
* Print out the mechanism policy for a kernel provider that has an entry
* in the kcf.conf file.
*
* The flag has_random is set to B_TRUE if the provider does random
* numbers. The flag has_mechs is set by the caller to B_TRUE if the provider
* has some mechanisms.
*
* If pent is NULL, the provider doesn't have a kcf.conf entry.
*/
void
{
}
/*
* TRANSLATION_NOTE
* This code block may need to be modified a bit to avoid
* constructing the text message on the fly.
*/
(void) printf(",");
}
(void) printf(".");
}
/*
* TRANSLATION_NOTE
* "random" is a keyword and not to be translated.
*/
if (rnd_disabled)
else if (has_random)
(void) printf("\n");
}
/*
* Check if a kernel software provider is in the kernel.
*
* Parameters:
* provname Provider name
* psoftlist_kernel Optional software provider list. If NULL, it will be
* obtained from get_soft_list().
* in_kernel Set to B_TRUE if device is in the kernel, else B_FALSE
*/
int
{
char *ptr;
int i;
return (FAILURE);
}
if (psoftlist_kernel == NULL) {
cryptodebug("failed to get the software provider list"
" from kernel.");
return (FAILURE);
}
}
for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
break;
}
}
if (psoftlist_allocated)
return (SUCCESS);
}
/*
* Check if a kernel hardware provider is in the kernel.
*
* Parameters:
* provname Provider name
* pdevlist Optional Hardware Crypto Device List. If NULL, it will be
* obtained from get_dev_list().
* in_kernel Set to B_TRUE if device is in the kernel, otherwise B_FALSE
*/
int
{
int inst_num;
int i;
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
}
for (i = 0; i < pdevlist->dl_dev_count; i++) {
break;
}
}
if (dev_list_allocated)
return (SUCCESS);
}