keystore.c revision 5c51f1241dbbdf2656d0e10011981411ed0c9673
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Module: keystore.c
* Description: This module contains the structure definitions for processing
* package keystore files.
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
#include <libintl.h>
#include <time.h>
#include <ctype.h>
#include <openssl/safestack.h>
#include "p12lib.h"
#include "pkgerr.h"
#include "keystore.h"
#include "pkglib.h"
#include "pkglibmsgs.h"
typedef struct keystore_t {
char *path;
char *passphrase;
/* truststore handles */
int cafd;
char *capath;
/* user certificate handles */
char *clpath;
/* private key handles */
char *keypath;
} keystore_t;
/* local routines */
static keystore_t *new_keystore(void);
static void free_keystore(keystore_t *);
long, keystore_t *);
static char *get_time_string(ASN1_TIME *);
/* locking routines */
static int file_lock(int, int, int);
static int file_unlock(int);
static boolean_t file_lock_test(int, int);
static boolean_t file_empty(char *);
static boolean_t wait_restore(int, char *, char *, char *);
/* wait on other keystore access for 1 minute before giving up */
#define LOCK_TIMEOUT 60
/*
* print_certs - prints certificates out of a keystore, to a file.
*
* Arguments:
* err - Error object to append errors to
* keystore - Keystore on which to operate
* alias - Name of certificate to print, NULL means print all
* format - Format in which to print certificates
* outfile - Where to print certificates
*
* Returns:
* 0 - Success
* non-zero - Failure, errors added to err
*/
int
{
int i;
/* print out each client cert */
&fname);
/* no name recorded, keystore is corrupt */
return (1);
}
/* name does not match, skip it */
(void) OPENSSL_free(fname);
continue;
} else {
(void) OPENSSL_free(fname);
}
}
}
(void) OPENSSL_free(fname);
}
/* print out each trusted cert */
(void) sunw_get_cert_fname(GETDO_COPY,
/* no name recorded, keystore is corrupt */
return (1);
}
/* name does not match, skip it */
(void) OPENSSL_free(fname);
continue;
} else {
(void) OPENSSL_free(fname);
}
}
}
(void) OPENSSL_free(fname);
}
if (found) {
return (0);
} else {
/* no certs printed */
} else {
}
return (1);
}
}
/*
* print_cert - prints a single certificate, to a file
*
* Arguments:
* err - Error object to append errors to
* x - The certificate to print
* alias - Name of certificate to print
* format - Format in which to print certificate
* outfile - Where to print certificate
*
* Returns:
* 0 - Success
* non-zero - Failure, errors added to err
*/
{
char *vdb_str;
char *vda_str;
int ret = 0;
char *tmp;
char *md5_fp;
char *sha1_fp;
int len;
/* need to localize the word "Fingerprint", hence these pointers */
char sha1_label[ATTR_MAX];
if (is_trusted) {
} else {
}
}
}
ret = 1;
goto cleanup;
}
} else {
/*
* make a copy, otherwise the next call to get_fingerprint
* will overwrite this one
*/
}
} else {
}
/* i18n: 14 characters max */
/* i18n: 14 characters max */
switch (format) {
case KEYSTORE_FORMAT_PEM:
(void) PEM_write_X509(outfile, x);
break;
case KEYSTORE_FORMAT_DER:
(void) i2d_X509_fp(outfile, x);
break;
case KEYSTORE_FORMAT_TEXT:
/* i18n: 18 characters max */
/* i18n: 18 characters max */
/* i18n: 18 characters max */
/* i18n: 18 characters max */
/* i18n: 18 characters max */
break;
default:
ret = 1;
goto cleanup;
}
return (ret);
}
/*
* open_keystore - Initialize new keystore object for
* impending access.
*
* Arguments:
* err - Error object to append errors to
* keystore_file - Base filename or directory of keystore
* app - Application making request
* passwd - Password used to decrypt keystore
* flags - Control flags used to control access mode and behavior
* result - Resulting keystore object stored here on success
*
* Returns:
* 0 - Success - result contains a pointer to the opened keystore
* non-zero - Failure, errors added to err
*/
int
{
int ret = 0;
tmpstore = new_keystore();
/* unable to determine keystore paths */
ret = 1;
goto cleanup;
}
/* unable to repair keystore */
ret = 1;
goto cleanup;
}
ret = 1;
goto cleanup;
}
/* now that we have locked the keystore, go ahead and read it */
ret = 1;
goto cleanup;
}
return (ret);
}
/*
* new_keystore - Allocates and initializes a Keystore object
*
* Arguments:
* NONE
*
* Returns:
* NULL - out of memory
* otherwise, returns a pointer to the newly allocated object,
* which should be freed with free_keystore() when no longer
* needed.
*/
static keystore_t
*new_keystore(void)
{
return (NULL);
}
return (tmpstore);
}
/*
* free_keystore - Deallocates a Keystore object
*
* Arguments:
* keystore - The keystore to deallocate
*
* Returns:
* NONE
*/
static void
{
}
}
/*
* close_keystore - Writes keystore to disk if needed, then
* unlocks and closes keystore.
*
* Arguments:
* err - Error object to append errors to
* keystore - Keystore which should be closed
* passwd - Password used to encrypt keystore
*
* Returns:
* 0 - Success - keystore is committed to disk, and unlocked
* non-zero - Failure, errors added to err
*/
int
{
int ret = 0;
/* write out the keystore first */
ret = 1;
goto cleanup;
}
}
ret = 1;
goto cleanup;
}
return (ret);
}
/*
* merge_ca_cert - Adds a trusted certificate (trust anchor) to a keystore.
* certificate checked for validity dates and non-duplicity.
*
* Arguments:
* err - Error object to add errors to
* cacert - Certificate which to merge into keystore
* keystore - The keystore into which the certificate is merged
*
* Returns:
* 0 - Success - Certificate passes validity, and
* is merged into keystore
* non-zero - Failure, errors recorded in err
*/
int
{
int ret = 0;
char *fname;
/* check validity dates */
ret = 1;
goto cleanup;
}
/* create the certificate's friendlyName */
ret = 1;
goto cleanup;
}
/* merge certificate into the keystore */
/* no existing truststore, so make a new one */
ret = 1;
goto cleanup;
}
} else {
/* existing truststore, make sure there's no duplicate */
ret = 1;
goto cleanup;
/* could not search properly! */
}
/* whoops, found one already */
ret = 1;
goto cleanup;
}
}
return (ret);
}
/*
* find_key_cert_pair - Searches a keystore for a matching
* public key certificate and private key, given an alias.
*
* Arguments:
* err - Error object to add errors to
* ks - Keystore to search
* alias - Name to used to match certificate's alias
* key - Resulting key is placed here
* cert - Resulting cert is placed here
*
* Returns:
* non-zero - Failure, errors recorded in err
*/
int
{
int ret = 0;
int items_found;
ret = 1;
goto cleanup;
}
/* no public certs */
ret = 1;
goto cleanup;
}
/* no private keys */
ret = 1;
goto cleanup;
}
/* try the easy case first */
/*
* only one private key and public key cert, and they
* match, so use them
*/
goto cleanup;
}
}
/* Attempt to find the right pair given the alias */
if ((items_found < 0) ||
ret = 1;
goto cleanup;
}
/* success */
return (ret);
}
/*
* find_ca_certs - Searches a keystore for trusted certificates
*
* Arguments:
* err - Error object to add errors to
* ks - Keystore to search
* cacerts - resulting set of trusted certs are placed here
*
* Returns:
* 0 - Success - trusted cert list returned in cacerts
* non-zero - Failure, errors recorded in err
*/
int
{
/* easy */
return (1);
}
return (0);
}
/*
* find_cl_certs - Searches a keystore for user certificates
*
* Arguments:
* err - Error object to add errors to
* ks - Keystore to search
* cacerts - resulting set of user certs are placed here
*
* No matching of any kind is performed.
* Returns:
* 0 - Success - trusted cert list returned in cacerts
* non-zero - Failure, errors recorded in err
*/
/* ARGSUSED */
int
{
/* easy */
return (0);
}
/*
* merge_cert_and_key - Adds a user certificate and matching
* private key to a keystore.
* certificate checked for validity dates and non-duplicity.
*
* Arguments:
* err - Error object to add errors to
* cert - Certificate which to merge into keystore
* key - matching private key to 'cert'
* alias - Name which to store the cert and key under
* keystore - The keystore into which the certificate is merged
*
* Returns:
* 0 - Success - Certificate passes validity, and
* is merged into keystore, along with key
* non-zero - Failure, errors recorded in err
*/
int
{
int ret = 0;
/* check validity dates */
ret = 1;
goto cleanup;
}
/* set the friendlyName of the key and cert to the supplied alias */
ret = 1;
goto cleanup;
}
/* merge certificate and key into the keystore */
/* no existing truststore, so make a new one */
ret = 1;
goto cleanup;
}
} else {
/* existing certstore, make sure there's no duplicate */
NULL, &existingcert) < 0) {
ret = 1;
goto cleanup;
/* could not search properly! */
}
if (existingcert != NULL) {
/* whoops, found one already */
ret = 1;
goto cleanup;
}
}
/* no existing keystore, so make a new one */
ret = 1;
goto cleanup;
}
} else {
/* existing keystore, so make sure there's no duplicate entry */
&existingkey, NULL) < 0) {
ret = 1;
goto cleanup;
/* could not search properly! */
}
if (existingkey != NULL) {
/* whoops, found one already */
ret = 1;
goto cleanup;
}
}
if (existingcert != NULL)
(void) X509_free(existingcert);
if (existingkey != NULL)
(void) sunw_evp_pkey_free(existingkey);
return (ret);
}
/*
* delete_cert_and_keys - Deletes one or more certificates
* and matching private keys from a keystore.
*
* Arguments:
* err - Error object to add errors to
* ks - The keystore from which certs and keys are deleted
* alias - Name which to search for certificates and keys
* to delete
*
* Returns:
* 0 - Success - All trusted certs which match 'alias'
* are deleted. All user certificates
* which match 'alias' are deleted, along
* with the matching private key.
* non-zero - Failure, errors recorded in err
*/
int
{
int i;
/* delete any and all client certs with the supplied name */
existingcert, &fname) >= 0) {
/* match, so nuke it */
existingcert = NULL;
}
(void) OPENSSL_free(fname);
}
}
/* we deleted all the client certs */
}
}
/* and now the private keys */
existingkey, &fname) >= 0) {
/* match, so nuke it */
existingkey = NULL;
}
(void) OPENSSL_free(fname);
}
}
/* we deleted all the private keys */
}
}
/* finally, remove any trust anchors that match */
existingcert, &fname) >= 0) {
/* match, so nuke it */
existingcert = NULL;
}
(void) OPENSSL_free(fname);
}
}
/* we deleted all the CA certs */
}
}
if (found) {
return (0);
} else {
/* no certs or keys deleted */
return (1);
}
}
/*
* check_cert - Checks certificate validity. This routine
* checks that the current time falls within the period
* of validity for the cert.
*
* Arguments:
* err - Error object to add errors to
* cert - The certificate to check
*
* Returns:
* 0 - Success - Certificate checks out
* non-zero - Failure, errors and reasons recorded in err
*/
int
{
char currtimestr[ATTR_MAX];
char *r, *before_str, *after_str;
/* get current time */
return (1);
}
/* trim whitespace from end of time string */
*r = '\0';
}
/* check validity of cert */
case CHKERR_TIME_OK:
/* Current time meets requested checks */
break;
case CHKERR_TIME_BEFORE_BAD:
/* 'not before' field is invalid */
case CHKERR_TIME_AFTER_BAD:
/* 'not after' field is invalid */
return (1);
case CHKERR_TIME_IS_BEFORE:
/* Current time is before 'not before' */
case CHKERR_TIME_HAS_EXPIRED:
/*
* Ignore expiration time since the trust cert used to
* verify the certs used to sign Sun patches is already
* expired. Once the patches get resigned with the new
* cert we will check expiration against the time the
* patch was signed and not the time it is installed.
*/
return (0);
default:
return (1);
}
/* all checks ok */
return (0);
}
/*
* check_cert - Checks certificate validity. This routine
* checks everything that check_cert checks, and additionally
* verifies that the private key and corresponding public
* key are indeed a pair.
*
* Arguments:
* err - Error object to add errors to
* cert - The certificate to check
* key - the key to check
* Returns:
* 0 - Success - Certificate checks out
* non-zero - Failure, errors and reasons recorded in err
*/
int
{
/* check validity dates */
return (1);
}
/* check key pair match */
return (1);
}
/* all checks OK */
return (0);
}
/* ------------------ private functions ---------------------- */
/*
* verify_keystore_integrity - Searches for the remnants
* of a failed or aborted keystore modification, and
* cleans up the files, retstores the keystore to a known
* state.
*
* Arguments:
* err - Error object to add errors to
* keystore_file - Base directory or filename of keystore
* app - Application making request
*
* Returns:
* 0 - Success - Keystore is restored, or untouched in the
* case that cleanup was unnecessary
* non-zero - Failure, errors and reasons recorded in err
*/
static boolean_t
{
return (B_FALSE);
}
}
return (B_FALSE);
}
}
return (B_FALSE);
}
}
return (B_TRUE);
}
/*
* restore_keystore_file - restores a keystore file to
* a known state.
*
* Keystore files can possibly be corrupted by a variety
* routine, along with write_keystore_file, tries to
* maintain keystore integrity by writing the files
* out in a particular order, minimizing the time period
* that the keystore is in an indeterminate state.
*
* With the current implementation, there are some failures
* that are wholly unrecoverable, such as disk corruption.
* These routines attempt to minimize the risk, but not
* eliminate it. When better, atomic operations are available
* (such as a trued atabase with commit, rollback, and
* guaranteed atomicity), this implementation should use that.
*
* Arguments:
* err - Error object to add errors to
* keystore_file - keystore file path to restore.
*
* Returns:
* 0 - Success - Keystore file is restored, or untouched in the
* case that cleanup was unnecessary
* non-zero - Failure, errors and reasons recorded in err
*/
/* ARGSUSED */
static boolean_t
{
char newpath[MAXPATHLEN];
char backuppath[MAXPATHLEN];
int newfd;
int len;
keystore_file)) < 0) ||
return (B_FALSE);
}
keystore_file)) < 0) ||
return (B_FALSE);
}
/*
* restore the file, waiting on it
* to be free for locking, or for
* it to disappear
*/
newpath, backuppath)) {
return (B_FALSE);
} else {
return (B_TRUE);
}
} else {
/* "new" file is not a regular file */
return (B_FALSE);
}
} else {
/* couldn't stat "new" file */
return (B_FALSE);
}
} else {
/* "new" file doesn't exist */
return (B_TRUE);
}
}
static boolean_t
char *origpath, char *backuppath)
{
(void) alarm(LOCK_TIMEOUT);
/* could not lock file */
(void) alarm(0);
return (B_FALSE);
}
(void) alarm(0);
/*
* The new file still
* exists, with no
* owner. It must be
* the result of an
* aborted update.
*/
if ((p12 =
/*
* The file
* appears
* complete.
* Replace the
* exsisting
* keystore
* file with
* this one
*/
} else {
/* The file is not complete. Remove it */
}
/* remove backup file */
(void) remove(backuppath);
return (B_TRUE);
} else {
/*
* new file exists, but is not a
* regular file
*/
return (B_FALSE);
}
} else {
/*
* could not stat file. Unless
* the reason was that the file
* is now gone, this is an error
*/
return (B_FALSE);
}
/*
* otherwise, file is gone. The process
* that held the lock must have
* successfully cleaned up and
* exited with a valid keystore
* state
*/
return (B_TRUE);
}
}
/*
* resolve_paths - figure out if we are dealing with a single-file
* or multi-file keystore
*
* The flags tell resolve_paths how to behave:
*
* KEYSTORE_PATH_SOFT
* If the keystore file does not exist at <base>/<app> then
* use <base> as the path to the keystore. This can be used,
* for example, to access an app-specific keystore iff it
* exists, otherwise revert back to an app-generic keystore.
*
* KEYSTORE_PATH_HARD
* Always use the keystore located at <keystore_path>/<app>.
* they will be created. This is used to avoid falling
* back to an app-generic keystore path when the app-specific
* one does not exist.
*
* Arguments:
* err - Error object to add errors to
* keystore_file - base keystore file path to lock
* app - Application making requests
* flags - Control flags (see above description)
* keystore - object which is being locked
*
* Returns:
* B_TRUE - Success - Keystore file is locked, paths to
* appropriate files placed in keystore.
* B_FALSE - Failure, errors and reasons recorded in err
*/
static boolean_t
{
/*
* figure out whether we are dealing with a single-file keystore
* or a multi-file keystore
*/
keystore_file, app)) < 0) ||
return (B_FALSE);
}
/*
* app-specific does not exist
* fallback to app-generic, if flags say we can
*/
if ((flags & KEYSTORE_PATH_MASK) ==
/*
* app-generic dir
* exists, so use it
* as a multi-file
* keystore
*/
/*
* app-generic file exists, so
* use it as a single file ks
*/
}
}
}
}
if (fd1 != -1)
if (fd2 != -1)
} else {
/*
* app-generic dir exists, so use
* it as a multi-file keystore
*/
}
if (fd1 != -1)
}
/* app-specific keystore */
} else {
/* app-generic keystore */
if (!multi) {
/* single-file app-generic keystore */
} else {
/* multi-file app-generic keystore */
}
}
return (B_TRUE);
}
/*
* lock_keystore - Locks a keystore for shared (read-only)
* or exclusive (read-write) access.
*
* The flags tell lock_keystore how to behave:
*
* KEYSTORE_ACCESS_READONLY
* opens keystore read-only. Attempts to modify results in an error
*
* KEYSTORE_ACCESS_READWRITE
* opens keystore read-write
*
* KEYSTORE_PATH_SOFT
* If the keystore file does not exist at <base>/<app> then
* use <base> as the path to the keystore. This can be used,
* for example, to access an app-specific keystore iff it
* exists, otherwise revert back to an app-generic keystore.
*
* KEYSTORE_PATH_HARD
* Always use the keystore located at <keystore_path>/<app>.
* they will be created. This is used to avoid falling
* back to an app-generic keystore path when the app-specific
* one does not exist.
*
* Arguments:
* err - Error object to add errors to
* flags - Control flags (see above description)
* keystore - object which is being locked
*
* Returns:
* 0 - Success - Keystore file is locked, paths to
* appropriate files placed in keystore.
* non-zero - Failure, errors and reasons recorded in err
*/
static boolean_t
{
switch (flags & KEYSTORE_ACCESS_MASK) {
case KEYSTORE_ACCESS_READONLY:
/*
* no keystore. try to create an
* empty one so we can lock on it and
* prevent others from gaining
* exclusive access. It will be
* deleted when the keystore is closed.
*/
goto cleanup;
}
} else {
goto cleanup;
}
}
0) == -1) {
goto cleanup;
}
} else {
/* ca file not a regular file! */
goto cleanup;
}
} else {
goto cleanup;
}
break;
/* does not exist. try to create an empty one */
goto cleanup;
}
} else {
goto cleanup;
}
}
0) == -1) {
goto cleanup;
}
} else {
/* ca file not a regular file! */
goto cleanup;
}
} else {
goto cleanup;
}
break;
default:
goto cleanup;
}
if (!ret) {
}
}
return (ret);
}
/*
* unlock_keystore - Unocks a keystore
*
* Arguments:
* err - Error object to add errors to
* keystore - keystore object to unlock
* Returns:
* 0 - Success - Keystore files are unlocked, files are closed,
* non-zero - Failure, errors and reasons recorded in err
*/
/* ARGSUSED */
static boolean_t
{
/*
* Release lock on the CA file.
* Delete file if it is empty
*/
}
return (B_TRUE);
}
/*
* read_keystore - Reads keystore files of disk, parses
* into internal structures.
*
* Arguments:
* err - Error object to add errors to
* keystore - keystore object to read into
* cb - callback to get password, if required
* Returns:
* 0 - Success - Keystore files are read, and placed
* into keystore structure.
* non-zero - Failure, errors and reasons recorded in err
*/
static boolean_t
{
}
if (!ca_empty) {
/* first read the ca file */
goto cleanup;
}
/* Get password, using callback if necessary */
if (!have_passwd) {
goto cleanup;
}
}
/* decrypt and parse keystore file */
/* could not parse the contents */
goto cleanup;
}
} else {
/*
* truststore is empty, so we don't have any trusted
* certs
*/
}
/*
* if there is no cl file or key file, use the cl's and key's found
* in the ca file
*/
goto cleanup;
}
} else {
/*
* files are in separate files. read keys out of the keystore
* certs out of the certstore, if they are not empty
*/
if (!cl_empty) {
goto cleanup;
}
/* Get password, using callback if necessary */
if (!have_passwd) {
keystore)) {
goto cleanup;
}
}
if (check_password(p12,
/*
* password in client cert file
* is different than
* the one in the other files!
*/
goto cleanup;
}
/* could not parse the contents */
goto cleanup;
}
} else {
}
if (!key_empty) {
goto cleanup;
}
/* Get password, using callback if necessary */
if (!have_passwd) {
keystore)) {
goto cleanup;
}
}
if (check_password(p12,
goto cleanup;
}
/* could not parse the contents */
goto cleanup;
}
} else {
}
}
return (ret);
}
/*
* get_keystore_password - retrieves pasword used to
* decrypt PKCS12 structure.
*
* Arguments:
* err - Error object to add errors to
* p12 - PKCS12 structure which returned password should
* decrypt
* cb - callback to collect password.
* keystore - The keystore in which the PKCS12 structure
* will eventually populate.
* Returns:
* B_TRUE - success.
* keystore password is set in keystore->passphrase.
* B_FALSE - failure, errors logged
*/
static boolean_t
{
char *passwd;
/* see if no password is the right password */
passwd = "";
} else {
/* oops, it's encrypted. get password */
&data) == -1) {
/* could not get password */
return (B_FALSE);
}
/* wrong password */
return (B_FALSE);
}
/*
* make copy of password buffer, since it
* goes away upon return
*/
}
return (B_TRUE);
}
/*
* write_keystore - Writes keystore files to disk
*
* Arguments:
* err - Error object to add errors to
* keystore - keystore object to write from
* passwd - password used to encrypt keystore
* Returns:
* 0 - Success - Keystore contents are written out to
* the same locations as read from
* non-zero - Failure, errors and reasons recorded in err
*/
static boolean_t
{
/*
* keystore is a file.
* just write out a single file
*/
/*
* no keys or certs to write out, so
* blank the ca file. we do not
* delete it since it is used as a
* lock by lock_keystore() in
* subsequent invocations
*/
goto cleanup;
}
} else {
/*
* if the keystore is being created for the first time,
* prompt for a passphrase for encryption
*/
goto cleanup;
}
} else {
/*
* use the one used when the keystore
* was read
*/
}
goto cleanup;
}
goto cleanup;
}
}
} else {
/* files are seprate. Do one at a time */
/*
* if the keystore is being created for the first time,
* prompt for a passphrase for encryption
*/
goto cleanup;
}
} else {
/* use the one used when the keystore was read */
}
/* do private keys first */
goto cleanup;
}
p12)) {
goto cleanup;
}
} else {
goto cleanup;
}
}
/* do user certs next */
goto cleanup;
}
goto cleanup;
}
} else {
goto cleanup;
}
}
/* finally do CA cert file */
goto cleanup;
}
goto cleanup;
}
} else {
/*
* nothing to write out, so truncate the file
* (it will be deleted during close_keystore)
*/
goto cleanup;
}
}
}
return (ret);
}
/*
* clear_keystore_file - Clears (zeros out) a keystore file.
*
* Arguments:
* err - Error object to add errors to
* dest - Path of keystore file to zero out.
* Returns:
* 0 - Success - Keystore file is truncated to zero length
* non-zero - Failure, errors and reasons recorded in err
*/
static boolean_t
{
int fd;
if (fd == -1) {
/* can't open for writing */
errno);
return (B_FALSE);
}
/* not a regular file */
dest);
return (B_FALSE);
}
return (B_FALSE);
}
return (B_TRUE);
}
/*
* write_keystore_file - Writes keystore file to disk.
*
* Keystore files can possibly be corrupted by a variety
* routine, along with restore_keystore_file, tries to
* maintain keystore integity by writing the files
* out in a particular order, minimizing the time period
* that the keystore is in an indeterminate state.
*
* With the current implementation, there are some failures
* that are wholly unrecoverable, such as disk corruption.
* These routines attempt to minimize the risk, but not
* eliminate it. When better, atomic operations are available
* (such as a true database with commit, rollback, and
* guaranteed atomicity), this implementation should use that.
*
*
* Arguments:
* err - Error object to add errors to
* dest - Destination filename
* contents - Contents to write to the file
* Returns:
* 0 - Success - Keystore contents are written out to
* the destination.
* non-zero - Failure, errors and reasons recorded in err
*/
static boolean_t
{
char newpath[MAXPATHLEN];
char backuppath[MAXPATHLEN];
int fd;
goto cleanup;
}
goto cleanup;
}
newpath);
goto cleanup;
}
goto cleanup;
}
newpath);
goto cleanup;
}
/* flush, then close */
/* now back up the original file */
/* put new one in its place */
/* remove backup */
(void) remove(backuppath);
if (fd != -1)
return (ret);
}
/*
* read_keystore_file - Reads single keystore file
* off disk in PKCS12 format.
*
* Arguments:
* err - Error object to add errors to
* file - File path to read
* Returns:
* PKCS12 contents of file, or NULL if an error occurred.
* errors recorded in 'err'.
*/
static PKCS12
{
int fd;
goto cleanup;
}
goto cleanup;
}
file);
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
if (fd != -1)
return (p12);
}
/*
* Locks the specified file.
*/
static int
{
if (!wait) {
/*
* The caller would have to wait to get the
* lock on this file.
*/
return (-1);
}
}
}
/*
* Returns FALSE if the file is not locked; TRUE
* otherwise.
*/
static boolean_t
{
/*
* The caller would have to wait to get the
* lock on this file.
*/
return (B_TRUE);
}
}
/*
* The file is not locked.
*/
return (B_FALSE);
}
/*
* Unlocks the specified file.
*/
static int
file_unlock(int fd)
{
}
/*
* Determines if file has a length of 0 or not
*/
static boolean_t
file_empty(char *path)
{
/* file is empty if size = 0 or it doesn't exist */
return (B_TRUE);
}
} else {
return (B_TRUE);
}
}
return (B_FALSE);
}
/*
* Name: get_time_string
* Description: Generates a human-readable string from an ASN1_TIME
*
* Arguments: intime - The time to convert
*
* Returns : A pointer to a static string representing the passed-in time.
*/
static char
{
char *p;
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (NULL);
}
/* trim the end of the string */
*p = '\0';
}
return (time);
}
/*
* check_password - do various password checks to see if the current password
* will work or we need to prompt for a new one.
*
* Arguments:
* pass - password to check
*
* Returns:
* B_TRUE - Password is OK.
* B_FALSE - Password not valid.
*/
static boolean_t
{
/*
* If password is zero length or NULL then try verifying both cases
* to determine which password is correct. The reason for this is that
* under PKCS#12 password based encryption no password and a zero
* length password are two different things...
*/
/* Check the mac */
}
return (ret);
}