diff options
Diffstat (limited to 'usr/src/cmd/cmd-crypto/pktool/download.c')
-rw-r--r-- | usr/src/cmd/cmd-crypto/pktool/download.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/download.c b/usr/src/cmd/cmd-crypto/pktool/download.c new file mode 100644 index 0000000000..1eabc85ee3 --- /dev/null +++ b/usr/src/cmd/cmd-crypto/pktool/download.c @@ -0,0 +1,274 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <malloc.h> +#include <libgen.h> +#include <fcntl.h> +#include <errno.h> +#include <cryptoutil.h> +#include "common.h" +#include <kmfapi.h> + +int +pk_download(int argc, char *argv[]) +{ + int rv; + int opt; + extern int optind_av; + extern char *optarg_av; + int oclass = 0; + char *url = NULL; + char *http_proxy = NULL; + char *dir = NULL; + char *outfile = NULL; + char *proxy = NULL; + int proxy_port = 0; + KMF_HANDLE_T kmfhandle = NULL; + KMF_ENCODE_FORMAT format; + KMF_RETURN ch_rv = KMF_OK; + char *fullpath = NULL; + KMF_DATA cert = {NULL, 0}; + KMF_DATA cert_der = {NULL, 0}; + + while ((opt = getopt_av(argc, argv, + "t:(objtype)u:(url)h:(http_proxy)o:(outfile)d:(dir)")) != EOF) { + + if (EMPTYSTRING(optarg_av)) + return (PK_ERR_USAGE); + switch (opt) { + case 't': + if (oclass) + return (PK_ERR_USAGE); + oclass = OT2Int(optarg_av); + if (!(oclass & (PK_CERT_OBJ | PK_CRL_OBJ))) + return (PK_ERR_USAGE); + break; + case 'u': + if (url) + return (PK_ERR_USAGE); + url = optarg_av; + break; + case 'h': + if (http_proxy) + return (PK_ERR_USAGE); + http_proxy = optarg_av; + break; + case 'o': + if (outfile) + return (PK_ERR_USAGE); + outfile = optarg_av; + break; + case 'd': + if (dir) + return (PK_ERR_USAGE); + dir = optarg_av; + break; + default: + cryptoerror(LOG_STDERR, gettext( + "unrecognized download option '%s'\n"), + argv[optind_av]); + return (PK_ERR_USAGE); + } + } + + /* No additional args allowed. */ + argc -= optind_av; + argv += optind_av; + if (argc) { + return (PK_ERR_USAGE); + } + + /* Check the dir and outfile options */ + if (outfile == NULL) { + /* If outfile is not specified, use the basename of URI */ + outfile = basename(url); + } + + fullpath = get_fullpath(dir, outfile); + if (fullpath == NULL) { + cryptoerror(LOG_STDERR, gettext("Incorrect dir or outfile " + "option value \n")); + return (PK_ERR_USAGE); + } + /* Check if the file exists and might be overwritten. */ + if (access(fullpath, F_OK) == 0) { + cryptoerror(LOG_STDERR, + gettext("Warning: file \"%s\" exists, " + "will be overwritten."), fullpath); + if (yesno(gettext("Continue with download? "), + gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { + return (0); + } + } else { + rv = verify_file(fullpath); + if (rv != KMF_OK) { + cryptoerror(LOG_STDERR, gettext("The file (%s) " + "cannot be created.\n"), fullpath); + return (PK_ERR_USAGE); + } + } + + + /* URI MUST be specified */ + if (url == NULL) { + cryptoerror(LOG_STDERR, gettext("A URL must be specified\n")); + rv = PK_ERR_USAGE; + goto end; + } + + /* + * Get the http proxy from the command "http_proxy" option or the + * environment variable. The command option has a higher priority. + */ + if (http_proxy == NULL) + http_proxy = getenv("http_proxy"); + + if (http_proxy != NULL) { + char *ptmp = http_proxy; + char *proxy_port_s; + + if (strncasecmp(ptmp, "http://", 7) == 0) + ptmp += 7; /* skip the scheme prefix */ + + proxy = strtok(ptmp, ":"); + proxy_port_s = strtok(NULL, "\0"); + if (proxy_port_s != NULL) + proxy_port = strtol(proxy_port_s, NULL, 0); + else + proxy_port = 8080; + } + + /* If objtype is not specified, default to CRL */ + if (oclass == 0) { + oclass = PK_CRL_OBJ; + } + + if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { + cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); + rv = PK_ERR_USAGE; + goto end; + } + + /* Now we are ready to download */ + if (oclass & PK_CRL_OBJ) { + rv = KMF_DownloadCRL(kmfhandle, url, proxy, proxy_port, 30, + fullpath, &format); + } else if (oclass & PK_CERT_OBJ) { + rv = KMF_DownloadCert(kmfhandle, url, proxy, proxy_port, 30, + fullpath, &format); + } + + if (rv != KMF_OK) { + switch (rv) { + case KMF_ERR_BAD_URI: + cryptoerror(LOG_STDERR, + gettext("Error in parsing URI\n")); + rv = PK_ERR_USAGE; + break; + case KMF_ERR_OPEN_FILE: + cryptoerror(LOG_STDERR, + gettext("Error in opening file\n")); + rv = PK_ERR_USAGE; + break; + case KMF_ERR_WRITE_FILE: + cryptoerror(LOG_STDERR, + gettext("Error in writing file\n")); + rv = PK_ERR_USAGE; + break; + case KMF_ERR_BAD_CRLFILE: + cryptoerror(LOG_STDERR, gettext("Not a CRL file\n")); + rv = PK_ERR_USAGE; + break; + case KMF_ERR_BAD_CERTFILE: + cryptoerror(LOG_STDERR, + gettext("Not a certificate file\n")); + rv = PK_ERR_USAGE; + break; + case KMF_ERR_MEMORY: + cryptoerror(LOG_STDERR, + gettext("Not enough memory\n")); + rv = PK_ERR_SYSTEM; + break; + default: + cryptoerror(LOG_STDERR, + gettext("Error in downloading the file.\n")); + rv = PK_ERR_SYSTEM; + break; + } + goto end; + } + + /* + * If the file is successfully downloaded, we also check the date. + * If the downloaded file is outdated, give a warning. + */ + if (oclass & PK_CRL_OBJ) { + KMF_CHECKCRLDATE_PARAMS params; + + params.crl_name = fullpath; + ch_rv = KMF_CheckCRLDate(kmfhandle, ¶ms); + + } else { /* certificate */ + ch_rv = KMF_ReadInputFile(kmfhandle, fullpath, &cert); + if (ch_rv != KMF_OK) + goto end; + + if (format == KMF_FORMAT_PEM) { + int len; + ch_rv = KMF_Pem2Der(cert.Data, cert.Length, + &cert_der.Data, &len); + if (ch_rv != KMF_OK) + goto end; + cert_der.Length = (size_t)len; + } + + ch_rv = KMF_CheckCertDate(kmfhandle, + format == KMF_FORMAT_ASN1 ? &cert : &cert_der); + } + +end: + if (ch_rv == KMF_ERR_VALIDITY_PERIOD) { + cryptoerror(LOG_STDERR, + gettext("Warning: the downloaded file is expired.\n")); + } else if (ch_rv != KMF_OK) { + cryptoerror(LOG_STDERR, + gettext("Warning: failed to check the validity.\n")); + } + + if (fullpath) + free(fullpath); + + KMF_FreeData(&cert); + KMF_FreeData(&cert_der); + + (void) KMF_Finalize(kmfhandle); + return (rv); +} |