/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2002-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <libintl.h>
#include <locale.h>
#include <sys/wanboot_impl.h>
#include <unistd.h>
#include <string.h>
#include <libinetutil.h>
#include <wanbootutil.h>
#include <p12aux.h>
static char *progname;
/* Returns from time_check */
typedef enum {
} time_errs_t;
static int parse_keyid(const char *);
static int do_certs(void);
static void usage(void);
static const char *cryptoerr(void);
int
{
int i;
/*
* Do the necessary magic for localization support.
*/
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
progname++;
else
switch (i) {
case 'v':
break;
case 'l':
if (parse_keyid(optarg) < 0)
return (EXIT_FAILURE);
break;
case 'c':
outfiles |= IO_CERTFILE;
break;
case 'k':
outfiles |= IO_KEYFILE;
break;
case 't':
outfiles |= IO_TRUSTFILE;
break;
case 'i':
break;
default:
usage();
}
}
wbku_printerr("no input file specified\n");
usage();
}
/*
* Need output files.
*/
if (outfiles == 0) {
wbku_printerr("at least one output file must be specified\n");
usage();
}
if (do_certs() < 0)
return (EXIT_FAILURE);
return (EXIT_SUCCESS);
}
static int
{
const char *rp;
char *wp;
char *nkeystr;
/*
* In the worst case, we'll need one additional character in our
* output string -- e.g. "A\0" -> "0A\0"
*/
wbku_printerr("cannot allocate keyid");
return (-1);
}
/*
* For convenience, we allow the user to put spaces between each digit
* when entering it on the command line. As a result, we need to
* process it into a format that hexascii_to_octet() can handle. Note
* that we're careful to map strings like "AA B CC D" to "AA0BCC0D".
*/
if (*rp == ' ')
continue;
} else {
}
}
*wp = '\0';
return (-1);
}
return (0);
}
static int
do_certs(void)
{
char *bufp;
return (-1);
if (verbose) {
/*
* sunw_subject_attrs() returns a pointer to
* memory allocated on our behalf. The same
* behavior is exhibited by sunw_issuer_attrs().
*/
bufp);
}
}
xcert_in);
}
X509 *x;
int i;
for (i = 0; i < sk_X509_num(ta_in); i++) {
/* LINTED */
x = sk_X509_value(ta_in, i);
(void) printf(
gettext("\nTrust Anchor cert %d:\n"), i);
/*
* sunw_subject_attrs() returns a pointer to
* memory allocated on our behalf. We get the
* same behavior from sunw_issuer_attrs().
*/
(void) printf(
}
(void) printf(
}
NULL, x);
}
}
}
wbku_printerr("warning: key and certificate do "
"not match\n");
}
}
}
static int
{
char *i_pass;
return (-1);
/*
* If we are only interested in getting a trust anchor, and if there
* is no trust anchor but is a regular cert, use it instead. Do this
* to handle the insanity with openssl, which requires a matching cert
* and key in order to write a PKCS12 file.
*/
if (outfiles == IO_TRUSTFILE) {
wbku_printerr("out of memory\n");
return (-1);
}
}
if (sk_X509_num(*t_in) == 0) {
wbku_printerr("out of memory\n");
return (-1);
}
}
}
}
wbku_printerr("no matching key found\n");
return (-1);
}
wbku_printerr("no matching certificate found\n");
return (-1);
}
wbku_printerr("no matching trust anchor found\n");
return (-1);
}
return (0);
}
static void
{
int i;
del_expired) {
}
}
return;
for (i = 0; i < sk_X509_num(ta_in); ) {
/* LINTED */
del_expired) {
/* LINTED */
continue;
}
i++;
}
}
static time_errs_t
{
int ret;
if (ret == CHK_TIME_OK)
return (CHK_TIME_OK);
switch (ret) {
case CHK_TIME_BEFORE_BAD:
gettext("\n Invalid cert 'not before' field\n"));
break;
case CHK_TIME_AFTER_BAD:
gettext("\n Invalid cert 'not after' field\n"));
break;
case CHK_TIME_HAS_EXPIRED:
break;
case CHK_TIME_IS_BEFORE:
break;
default:
break;
}
return (ret);
}
static time_errs_t
{
int i;
if (i == 0)
return (CHK_TIME_BEFORE_BAD);
if (i > 0)
return (CHK_TIME_IS_BEFORE);
/* After 'not before' time */
if (i == 0)
return (CHK_TIME_AFTER_BAD);
if (i < 0)
return (CHK_TIME_HAS_EXPIRED);
return (CHK_TIME_OK);
}
static int
{
if (verbose)
return (-1);
}
if (verbose)
return (-1);
}
if (verbose)
progname);
return (-1);
}
return (0);
}
static int
{
int ret;
return (-1);
}
return (-1);
}
return (-1);
}
if (ret <= 0) {
if (ret == 0)
wbku_printerr("cannot find matching cert and key\n");
else
cryptoerr());
return (-1);
}
return (0);
}
static int
{
int ret = 0;
return (-1);
}
return (-1);
}
wbku_printerr("out of memory\n");
ret = -1;
goto cleanup;
}
wbku_printerr("out of memory\n");
ret = -1;
goto cleanup;
}
wbku_printerr("out of memory\n");
ret = -1;
goto cleanup;
}
ret = -1;
goto cleanup;
}
ret = -1;
goto cleanup;
}
/*
* Put the cert and pkey off of the stack so that they won't
* be freed two times. (If they get left in the stack then
* they will be freed with the stack.)
*/
/* LINTED */
(void) sk_X509_delete(clist, 0);
}
}
/* LINTED */
(void) sk_EVP_PKEY_delete(klist, 0);
}
}
return (ret);
}
static void
usage(void)
{
gettext("usage:\n"
" %s -i <file> -c <file> -k <file> -t <file> [-l <keyid> -v]\n"
"\n"),
progname);
gettext(" where:\n"
" -i - input file to be split into component parts and put in\n"
" files given by -c, -k and -t\n"
" -c - output file for the client certificate\n"
" -k - output file for the client private key\n"
" -t - output file for the remaining certificates (assumed\n"
" to be trust anchors)\n"
"\n Files are assumed to be pkcs12-format files.\n\n"
" -v - verbose\n"
" -l - value of 'localkeyid' attribute in client cert and\n"
" private key to be selected from the input file.\n\n"));
}
/*
* Return a pointer to a static buffer that contains a listing of crypto
* errors. We presume that the user doesn't want more than 8KB of error
* messages :-)
*/
static const char *
cryptoerr(void)
{
const char *pfile;
int line;
unsigned int nerr = 0;
errbuf[0] = '\0';
if (++nerr > 1)
sizeof (errbuf));
break;
}
sizeof (errbuf));
}
return (errbuf);
}