/*
* 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
*
*/
#include <stdlib.h>
#include <ctype.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <libgen.h>
#include <kmfapiP.h>
typedef struct {
char *ekuname;
} EKUName2OID;
};
static void
{
return;
}
}
static void
{
xmlNodePtr n;
char *c;
while (n != NULL) {
(const xmlChar *)KMF_OCSP_BASIC_ELEMENT)) {
(char *)xmlGetProp(n,
(const xmlChar *)KMF_OCSP_RESPONDER_ATTR);
(const xmlChar *)KMF_OCSP_PROXY_ATTR);
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_OCSP_URI_ATTR);
xmlFree(c);
}
(char *)xmlGetProp(n,
(const xmlChar *)KMF_OCSP_RESPONSE_LIFETIME_ATTR);
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_OCSP_IGNORE_SIGN_ATTR);
xmlFree(c);
}
(const xmlChar *)KMF_OCSP_RESPONDER_CERT_ELEMENT)) {
(char *)xmlGetProp(n,
(const xmlChar *)KMF_CERT_NAME_ATTR);
(char *)xmlGetProp(n,
(const xmlChar *)KMF_CERT_SERIAL_ATTR);
}
n = n->next;
}
}
/*
* Parse the "validation-methods" section of the policy.
*/
static void
{
xmlNodePtr n;
char *c;
while (n != NULL) {
(const xmlChar *)KMF_OCSP_ELEMENT)) {
(const xmlChar *)KMF_CRL_ELEMENT)) {
(const xmlChar *)KMF_CRL_BASENAME_ATTR);
(const xmlChar *)KMF_CRL_DIRECTORY_ATTR);
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_CRL_GET_URI_ATTR);
} else {
}
xmlFree(c);
(const xmlChar *)KMF_CRL_PROXY_ATTR);
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_CRL_IGNORE_SIGN_ATTR);
} else {
}
xmlFree(c);
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_CRL_IGNORE_DATE_ATTR);
} else {
}
xmlFree(c);
}
n = n->next;
}
}
char *
{
if (bitfield & KMF_digitalSignature)
return ("digitalSignature");
if (bitfield & KMF_nonRepudiation)
return ("nonRepudiation");
if (bitfield & KMF_keyEncipherment)
return ("keyEncipherment");
if (bitfield & KMF_dataEncipherment)
return ("dataEncipherment");
if (bitfield & KMF_keyAgreement)
return ("keyAgreement");
if (bitfield & KMF_keyCertSign)
return ("keyCertSign");
if (bitfield & KMF_cRLSign)
return ("cRLSign");
if (bitfield & KMF_encipherOnly)
return ("encipherOnly");
if (bitfield & KMF_decipherOnly)
return ("decipherOnly");
return (NULL);
}
{
return (0);
return (KMF_digitalSignature);
return (KMF_nonRepudiation);
return (KMF_keyEncipherment);
return (KMF_dataEncipherment);
return (KMF_keyAgreement);
return (KMF_keyCertSign);
return (KMF_cRLSign);
return (KMF_encipherOnly);
return (KMF_decipherOnly);
return (0);
}
static void
{
xmlNodePtr n;
char *c;
while (n != NULL) {
(const xmlChar *)KMF_KEY_USAGE_ELEMENT)) {
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_KEY_USAGE_USE_ATTR);
if (c) {
*kubits |= kmf_string_to_ku(c);
xmlFree(c);
}
}
n = n->next;
}
}
static KMF_OID *
{
return (NULL);
return (NULL);
}
return (oid);
}
KMF_OID *
{
int i;
return (NULL);
for (i = 0; i < num_ekus; i++) {
return (oid);
}
}
return (NULL);
}
char *
{
int i;
for (i = 0; i < num_ekus; i++) {
}
}
return (NULL);
}
static KMF_RETURN
{
xmlNodePtr n;
char *c;
(const xmlChar *)KMF_EKU_NAME_ELEMENT)) {
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_EKU_NAME_ATTR);
if (c != NULL) {
oidptr = kmf_ekuname_to_oid(c);
xmlFree(c);
}
(const xmlChar *)KMF_EKU_OID_ELEMENT)) {
c = (char *)xmlGetProp(n,
(const xmlChar *)KMF_EKU_OID_ATTR);
if (c != NULL) {
(void) kmf_string_to_oid(c, &newoid);
xmlFree(c);
}
} else {
n = n->next;
continue;
}
} else {
}
} else {
}
n = n->next;
}
return (ret);
}
static KMF_RETURN
{
xmlNodePtr n;
n = node;
(const xmlChar *)KMF_CERT_MAPPER_NAME_ATTR);
(const xmlChar *)KMF_CERT_MAPPER_DIR_ATTR);
(const xmlChar *)KMF_CERT_MAPPER_PATH_ATTR);
(const xmlChar *)KMF_CERT_MAPPER_OPTIONS_ATTR);
/*
* These are set according to whether mapper setting is taken from the
* database or init function attributes.
*/
return (KMF_OK);
}
int
{
int ret = 0;
char *c;
(const xmlChar *)KMF_POLICY_NAME_ATTR);
c = (char *)xmlGetProp(node,
(const xmlChar *)KMF_OPTIONS_IGNORE_DATE_ATTR);
if (c && !strcasecmp(c, "true")) {
}
c = (char *)xmlGetProp(node,
(const xmlChar *)KMF_OPTIONS_IGNORE_UNKNOWN_EKUS);
if (c && !strcasecmp(c, "true")) {
xmlFree(c);
}
c = (char *)xmlGetProp(node,
(const xmlChar *)KMF_OPTIONS_IGNORE_TRUST_ANCHOR);
if (c && !strcasecmp(c, "true")) {
xmlFree(c);
}
c = (char *)xmlGetProp(node,
(const xmlChar *)KMF_OPTIONS_VALIDITY_ADJUSTTIME);
if (c) {
policy->validity_adjusttime = c;
} else {
}
(const xmlChar *)KMF_POLICY_TA_NAME_ATTR);
(const xmlChar *)KMF_POLICY_TA_SERIAL_ATTR);
}
while (n != NULL) {
(const xmlChar *)KMF_VALIDATION_METHODS_ELEMENT))
policy);
(const xmlChar *)KMF_KEY_USAGE_SET_ELEMENT))
(const xmlChar *)KMF_EKU_ELEMENT)) {
return (ret);
(const xmlChar *)KMF_CERT_MAPPER_ELEMENT)) {
return (ret);
}
n = n->next;
}
}
return (ret);
}
static int
{
return (-1);
}
}
return (0);
}
/*
* Add CRL policy information to the XML tree.
* Return non-zero on any failure, else 0 for success.
*
* This function is called only when the KMF_REVOCATION_METHOD_CRL flag is on.
*/
static int
{
xmlNodePtr n;
if (n == NULL)
return (-1);
if (crlinfo->basefilename &&
return (-1);
return (-1);
if (crlinfo->get_crl_uri &&
return (-1);
}
return (-1);
if (crlinfo->ignore_crl_sign &&
return (-1);
}
if (crlinfo->ignore_crl_date &&
return (-1);
}
return (0);
}
/*
* Add OCSP information to the policy tree.
* Return non-zero on any failure, else 0 for success.
*
* This function is called only when the KMF_REVOCATION_METHOD_OCSP flag is on.
*/
static int
{
int ret = 0;
/* basic node */
return (-1);
return (-1);
return (-1);
return (-1);
if (basic->uri_from_cert &&
return (-1);
if (basic->response_lifetime &&
return (-1);
if (basic->ignore_response_sign &&
return (-1);
/* responder cert node */
if (ocsp->has_resp_cert) {
(const xmlChar *)KMF_OCSP_RESPONDER_CERT_ELEMENT,
NULL);
return (-1);
return (-1);
return (-1);
}
}
return (ret);
}
/*
* Add validation method information to the policy tree.
* Return non-zero on any failure, else 0 for success.
*/
static int
{
int ret = 0;
return (-1);
goto end;
}
goto end;
}
end:
if (ret != 0) {
}
return (ret);
}
/*
* Add mapper policy info to the policy tree.
* Return non-zero on any failure, else 0 for success.
*/
static KMF_RETURN
{
if (mapper_node == NULL)
return (KMF_ERR_POLICY_ENGINE);
goto end;
}
goto end;
}
goto end;
}
}
end:
}
return (ret);
}
/*
* Add Key Usage information to the policy tree.
* Return non-zero on any failure, else 0 for success.
*/
static KMF_RETURN
{
int i;
if (kubits == 0)
return (0);
return (KMF_ERR_POLICY_ENGINE);
if (s != NULL) {
}
}
}
return (ret);
}
/*
* Add Extended-Key-Usage information to the policy tree.
* Return non-zero on any failure, else 0 for success.
*/
static KMF_RETURN
{
int i;
if (n == NULL)
return (KMF_ERR_POLICY_ENGINE);
if (s != NULL) {
addFormatting(n, "\n\t\t");
(const xmlChar *)KMF_EKU_OID_ELEMENT,
NULL);
free(s);
} else {
}
}
addFormatting(n, "\n\t");
}
xmlUnlinkNode(n);
xmlFreeNode(n);
}
return (ret);
}
void
{
int i;
}
}
}
void
{
return;
}
/*
* kmf_get_policy
*
* Find a policy record in the database.
*/
{
int found = 0;
return (KMF_ERR_BAD_PARAMETER);
/* Create a parser context */
ctxt = xmlNewParserCtxt();
return (KMF_ERR_POLICY_DB_FORMAT);
/* Read the policy DB and verify it against the schema. */
goto out;
}
goto out;
}
char *c;
/*
* Search for the policy that matches the given name.
*/
(const xmlChar *)KMF_POLICY_ELEMENT)) {
/* Check the name attribute */
c = (char *)xmlGetProp(node,
(const xmlChar *)KMF_POLICY_NAME_ATTR);
/* If a match, parse the rest of the data */
if (c != NULL) {
if (strcmp(c, policy_name) == 0) {
}
xmlFree(c);
}
}
}
if (!found) {
goto out;
}
out:
return (ret);
}
/*
* kmf_set_policy
*
* Set the policy record in the handle. This searches
* the policy DB for the named policy. If it is not found
* or an error occurred in processing, the existing policy
* is kept and an error code is returned.
*/
{
return (ret);
return (KMF_ERR_MEMORY);
goto out;
goto out;
/* release the existing policy data (if any). */
}
out:
/* Cleanup any data allocated before the error occurred */
}
return (ret);
}
static KMF_RETURN
{
int found = 0;
char *c;
/*
* Search for the policy that matches the given name.
*/
(const xmlChar *)KMF_POLICY_ELEMENT)) {
/* Check the name attribute */
c = (char *)xmlGetProp(node,
(const xmlChar *)KMF_POLICY_NAME_ATTR);
/* If a match, parse the rest of the data */
if (c != NULL) {
if (strcmp(c, policy_name) == 0) {
found = 1;
}
xmlFree(c);
}
}
if (!found)
}
/* Unlink the node */
/* Delete it from the document tree */
} else {
}
return (ret);
}
/*
* update_policyfile
*
* Attempt to do a "safe" file update as follows:
* 1. Lock the original file.
* 2. Create and write to a temporary file
* 3. Replace the original file with the temporary file.
*/
static KMF_RETURN
{
char *p;
/*
* Open and lock the DB file. First try to open an existing file,
* if that fails, open it as if it were new.
*/
return (KMF_ERR_POLICY_DB_FILE);
return (KMF_ERR_POLICY_DB_FILE);
}
/*
* Create a temporary file to hold the new data.
*/
if (p == NULL) {
/*
* filename contains basename only so we
* create a temp file in current directory.
*/
sizeof (tmpfilename)) >= sizeof (tmpfilename))
return (KMF_ERR_INTERNAL);
} else {
/*
* create a temp file in the same directory
* as the policy file.
*/
prefix_len = p - filename;
sizeof (TMPFILE_TEMPLATE));
}
if (tmpfd == -1) {
return (KMF_ERR_POLICY_DB_FILE);
}
(void) unlink(tmpfilename);
return (KMF_ERR_POLICY_DB_FILE);
}
/*
* Write the new info to the temporary file.
*/
(void) unlink(tmpfilename);
return (KMF_ERR_POLICY_ENGINE);
}
(void) unlink(tmpfilename);
return (KMF_ERR_POLICY_DB_FILE);
}
return (KMF_ERR_POLICY_DB_FILE);
/*
* Replace the original file with the updated tempfile.
*/
}
/* try to remove the tmp file */
(void) unlink(tmpfilename);
}
return (ret);
}
/*
* kmf_delete_policy_from_db
*
* Find a policy by name and remove it from the policy DB file.
* If the policy is not found, return an error.
*/
{
return (KMF_ERR_BAD_PARAMETER);
/*
* Cannot delete the default policy record from the system
* default policy database (/etc/security/kmfpolicy.xml).
*/
return (KMF_ERR_BAD_PARAMETER);
/* Make sure the policy file exists */
return (KMF_ERR_BAD_PARAMETER);
/* Read the policy DB and verify it against the schema. */
ctxt = xmlNewParserCtxt();
return (KMF_ERR_POLICY_DB_FORMAT);
goto end;
}
return (KMF_ERR_POLICY_DB_FORMAT);
}
end:
return (ret);
}
/*
* Add a new policy node to the Policy DB XML tree.
*/
static KMF_RETURN
{
goto out;
}
if (policy->ignore_date) {
"TRUE")) {
goto out;
}
}
if (policy->ignore_unknown_ekus) {
"TRUE")) {
goto out;
}
}
if (policy->ignore_trust_anchor) {
"TRUE")) {
goto out;
}
}
if (policy->validity_adjusttime) {
goto out;
}
}
goto out;
}
goto out;
}
/* Add a text node for readability */
goto out;
}
goto out;
}
goto out;
}
goto out;
}
} else {
}
out:
}
return (ret);
}
{
return (KMF_ERR_POLICY_NAME);
/* Check the TA related policy */
} else {
/*
* If the TA cert is set, then both name and serial number
* need to be specified.
*/
return (KMF_ERR_TA_POLICY);
}
return (KMF_ERR_TA_POLICY);
/*
* For OCSP, either use a fixed responder or use the
* value from the cert, but not both.
*/
return (KMF_ERR_OCSP_POLICY);
/*
* If the OCSP responder cert is set, then both name and serial
* number need to be specified.
*/
return (KMF_ERR_OCSP_POLICY);
}
return (ret);
}
/*
* Update the KMF policy file by creating a new XML Policy doc tree
* from the data in the KMF_POLICY_RECORD structure. If "check_policy"
* is true, then we check the policy sanity also.
*/
{
return (KMF_ERR_BAD_PARAMETER);
if (check_policy == B_TRUE) {
return (ret);
}
/* If the policyDB exists, load it into memory */
/* Create a parser context */
ctxt = xmlNewParserCtxt();
return (KMF_ERR_POLICY_DB_FORMAT);
goto out;
}
goto out;
}
/*
* If the DB has an existing policy of the
* same name, delete it from the tree.
*/
if (ret == KMF_ERR_POLICY_NOT_FOUND)
} else {
/* Initialize a new DB tree */
return (KMF_ERR_POLICY_ENGINE);
/*
* Add the DOCTYPE header to the tree so the
* DTD link is embedded
*/
(const xmlChar *)KMF_POLICY_ROOT,
}
}
/* Append the new policy info to the root node. */
/* If that worked, update the DB file. */
} else {
}
out:
return (ret);
}