summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-crypto/pktool/download.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/cmd-crypto/pktool/download.c')
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/download.c274
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, &params);
+
+ } 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);
+}