1*3089Swyllys /* 2*3089Swyllys * CDDL HEADER START 3*3089Swyllys * 4*3089Swyllys * The contents of this file are subject to the terms of the 5*3089Swyllys * Common Development and Distribution License (the "License"). 6*3089Swyllys * You may not use this file except in compliance with the License. 7*3089Swyllys * 8*3089Swyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3089Swyllys * or http://www.opensolaris.org/os/licensing. 10*3089Swyllys * See the License for the specific language governing permissions 11*3089Swyllys * and limitations under the License. 12*3089Swyllys * 13*3089Swyllys * When distributing Covered Code, include this CDDL HEADER in each 14*3089Swyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3089Swyllys * If applicable, add the following below this CDDL HEADER, with the 16*3089Swyllys * fields enclosed by brackets "[]" replaced with your own identifying 17*3089Swyllys * information: Portions Copyright [yyyy] [name of copyright owner] 18*3089Swyllys * 19*3089Swyllys * CDDL HEADER END 20*3089Swyllys */ 21*3089Swyllys /* 22*3089Swyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*3089Swyllys * Use is subject to license terms. 24*3089Swyllys */ 25*3089Swyllys 26*3089Swyllys #pragma ident "%Z%%M% %I% %E% SMI" 27*3089Swyllys 28*3089Swyllys #include <stdio.h> 29*3089Swyllys #include <stdlib.h> 30*3089Swyllys #include <string.h> 31*3089Swyllys #include <ctype.h> 32*3089Swyllys #include <malloc.h> 33*3089Swyllys #include <libgen.h> 34*3089Swyllys #include <fcntl.h> 35*3089Swyllys #include <errno.h> 36*3089Swyllys #include <cryptoutil.h> 37*3089Swyllys #include "common.h" 38*3089Swyllys #include <kmfapi.h> 39*3089Swyllys 40*3089Swyllys int 41*3089Swyllys pk_download(int argc, char *argv[]) 42*3089Swyllys { 43*3089Swyllys int rv; 44*3089Swyllys int opt; 45*3089Swyllys extern int optind_av; 46*3089Swyllys extern char *optarg_av; 47*3089Swyllys int oclass = 0; 48*3089Swyllys char *url = NULL; 49*3089Swyllys char *http_proxy = NULL; 50*3089Swyllys char *dir = NULL; 51*3089Swyllys char *outfile = NULL; 52*3089Swyllys char *proxy = NULL; 53*3089Swyllys int proxy_port = 0; 54*3089Swyllys KMF_HANDLE_T kmfhandle = NULL; 55*3089Swyllys KMF_ENCODE_FORMAT format; 56*3089Swyllys KMF_RETURN ch_rv = KMF_OK; 57*3089Swyllys char *fullpath = NULL; 58*3089Swyllys KMF_DATA cert = {NULL, 0}; 59*3089Swyllys KMF_DATA cert_der = {NULL, 0}; 60*3089Swyllys 61*3089Swyllys while ((opt = getopt_av(argc, argv, 62*3089Swyllys "t:(objtype)u:(url)h:(http_proxy)o:(outfile)d:(dir)")) != EOF) { 63*3089Swyllys 64*3089Swyllys if (EMPTYSTRING(optarg_av)) 65*3089Swyllys return (PK_ERR_USAGE); 66*3089Swyllys switch (opt) { 67*3089Swyllys case 't': 68*3089Swyllys if (oclass) 69*3089Swyllys return (PK_ERR_USAGE); 70*3089Swyllys oclass = OT2Int(optarg_av); 71*3089Swyllys if (!(oclass & (PK_CERT_OBJ | PK_CRL_OBJ))) 72*3089Swyllys return (PK_ERR_USAGE); 73*3089Swyllys break; 74*3089Swyllys case 'u': 75*3089Swyllys if (url) 76*3089Swyllys return (PK_ERR_USAGE); 77*3089Swyllys url = optarg_av; 78*3089Swyllys break; 79*3089Swyllys case 'h': 80*3089Swyllys if (http_proxy) 81*3089Swyllys return (PK_ERR_USAGE); 82*3089Swyllys http_proxy = optarg_av; 83*3089Swyllys break; 84*3089Swyllys case 'o': 85*3089Swyllys if (outfile) 86*3089Swyllys return (PK_ERR_USAGE); 87*3089Swyllys outfile = optarg_av; 88*3089Swyllys break; 89*3089Swyllys case 'd': 90*3089Swyllys if (dir) 91*3089Swyllys return (PK_ERR_USAGE); 92*3089Swyllys dir = optarg_av; 93*3089Swyllys break; 94*3089Swyllys default: 95*3089Swyllys cryptoerror(LOG_STDERR, gettext( 96*3089Swyllys "unrecognized download option '%s'\n"), 97*3089Swyllys argv[optind_av]); 98*3089Swyllys return (PK_ERR_USAGE); 99*3089Swyllys } 100*3089Swyllys } 101*3089Swyllys 102*3089Swyllys /* No additional args allowed. */ 103*3089Swyllys argc -= optind_av; 104*3089Swyllys argv += optind_av; 105*3089Swyllys if (argc) { 106*3089Swyllys return (PK_ERR_USAGE); 107*3089Swyllys } 108*3089Swyllys 109*3089Swyllys /* Check the dir and outfile options */ 110*3089Swyllys if (outfile == NULL) { 111*3089Swyllys /* If outfile is not specified, use the basename of URI */ 112*3089Swyllys outfile = basename(url); 113*3089Swyllys } 114*3089Swyllys 115*3089Swyllys fullpath = get_fullpath(dir, outfile); 116*3089Swyllys if (fullpath == NULL) { 117*3089Swyllys cryptoerror(LOG_STDERR, gettext("Incorrect dir or outfile " 118*3089Swyllys "option value \n")); 119*3089Swyllys return (PK_ERR_USAGE); 120*3089Swyllys } 121*3089Swyllys /* Check if the file exists and might be overwritten. */ 122*3089Swyllys if (access(fullpath, F_OK) == 0) { 123*3089Swyllys cryptoerror(LOG_STDERR, 124*3089Swyllys gettext("Warning: file \"%s\" exists, " 125*3089Swyllys "will be overwritten."), fullpath); 126*3089Swyllys if (yesno(gettext("Continue with download? "), 127*3089Swyllys gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 128*3089Swyllys return (0); 129*3089Swyllys } 130*3089Swyllys } else { 131*3089Swyllys rv = verify_file(fullpath); 132*3089Swyllys if (rv != KMF_OK) { 133*3089Swyllys cryptoerror(LOG_STDERR, gettext("The file (%s) " 134*3089Swyllys "cannot be created.\n"), fullpath); 135*3089Swyllys return (PK_ERR_USAGE); 136*3089Swyllys } 137*3089Swyllys } 138*3089Swyllys 139*3089Swyllys 140*3089Swyllys /* URI MUST be specified */ 141*3089Swyllys if (url == NULL) { 142*3089Swyllys cryptoerror(LOG_STDERR, gettext("A URL must be specified\n")); 143*3089Swyllys rv = PK_ERR_USAGE; 144*3089Swyllys goto end; 145*3089Swyllys } 146*3089Swyllys 147*3089Swyllys /* 148*3089Swyllys * Get the http proxy from the command "http_proxy" option or the 149*3089Swyllys * environment variable. The command option has a higher priority. 150*3089Swyllys */ 151*3089Swyllys if (http_proxy == NULL) 152*3089Swyllys http_proxy = getenv("http_proxy"); 153*3089Swyllys 154*3089Swyllys if (http_proxy != NULL) { 155*3089Swyllys char *ptmp = http_proxy; 156*3089Swyllys char *proxy_port_s; 157*3089Swyllys 158*3089Swyllys if (strncasecmp(ptmp, "http://", 7) == 0) 159*3089Swyllys ptmp += 7; /* skip the scheme prefix */ 160*3089Swyllys 161*3089Swyllys proxy = strtok(ptmp, ":"); 162*3089Swyllys proxy_port_s = strtok(NULL, "\0"); 163*3089Swyllys if (proxy_port_s != NULL) 164*3089Swyllys proxy_port = strtol(proxy_port_s, NULL, 0); 165*3089Swyllys else 166*3089Swyllys proxy_port = 8080; 167*3089Swyllys } 168*3089Swyllys 169*3089Swyllys /* If objtype is not specified, default to CRL */ 170*3089Swyllys if (oclass == 0) { 171*3089Swyllys oclass = PK_CRL_OBJ; 172*3089Swyllys } 173*3089Swyllys 174*3089Swyllys if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 175*3089Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 176*3089Swyllys rv = PK_ERR_USAGE; 177*3089Swyllys goto end; 178*3089Swyllys } 179*3089Swyllys 180*3089Swyllys /* Now we are ready to download */ 181*3089Swyllys if (oclass & PK_CRL_OBJ) { 182*3089Swyllys rv = KMF_DownloadCRL(kmfhandle, url, proxy, proxy_port, 30, 183*3089Swyllys fullpath, &format); 184*3089Swyllys } else if (oclass & PK_CERT_OBJ) { 185*3089Swyllys rv = KMF_DownloadCert(kmfhandle, url, proxy, proxy_port, 30, 186*3089Swyllys fullpath, &format); 187*3089Swyllys } 188*3089Swyllys 189*3089Swyllys if (rv != KMF_OK) { 190*3089Swyllys switch (rv) { 191*3089Swyllys case KMF_ERR_BAD_URI: 192*3089Swyllys cryptoerror(LOG_STDERR, 193*3089Swyllys gettext("Error in parsing URI\n")); 194*3089Swyllys rv = PK_ERR_USAGE; 195*3089Swyllys break; 196*3089Swyllys case KMF_ERR_OPEN_FILE: 197*3089Swyllys cryptoerror(LOG_STDERR, 198*3089Swyllys gettext("Error in opening file\n")); 199*3089Swyllys rv = PK_ERR_USAGE; 200*3089Swyllys break; 201*3089Swyllys case KMF_ERR_WRITE_FILE: 202*3089Swyllys cryptoerror(LOG_STDERR, 203*3089Swyllys gettext("Error in writing file\n")); 204*3089Swyllys rv = PK_ERR_USAGE; 205*3089Swyllys break; 206*3089Swyllys case KMF_ERR_BAD_CRLFILE: 207*3089Swyllys cryptoerror(LOG_STDERR, gettext("Not a CRL file\n")); 208*3089Swyllys rv = PK_ERR_USAGE; 209*3089Swyllys break; 210*3089Swyllys case KMF_ERR_BAD_CERTFILE: 211*3089Swyllys cryptoerror(LOG_STDERR, 212*3089Swyllys gettext("Not a certificate file\n")); 213*3089Swyllys rv = PK_ERR_USAGE; 214*3089Swyllys break; 215*3089Swyllys case KMF_ERR_MEMORY: 216*3089Swyllys cryptoerror(LOG_STDERR, 217*3089Swyllys gettext("Not enough memory\n")); 218*3089Swyllys rv = PK_ERR_SYSTEM; 219*3089Swyllys break; 220*3089Swyllys default: 221*3089Swyllys cryptoerror(LOG_STDERR, 222*3089Swyllys gettext("Error in downloading the file.\n")); 223*3089Swyllys rv = PK_ERR_SYSTEM; 224*3089Swyllys break; 225*3089Swyllys } 226*3089Swyllys goto end; 227*3089Swyllys } 228*3089Swyllys 229*3089Swyllys /* 230*3089Swyllys * If the file is successfully downloaded, we also check the date. 231*3089Swyllys * If the downloaded file is outdated, give a warning. 232*3089Swyllys */ 233*3089Swyllys if (oclass & PK_CRL_OBJ) { 234*3089Swyllys KMF_CHECKCRLDATE_PARAMS params; 235*3089Swyllys 236*3089Swyllys params.crl_name = fullpath; 237*3089Swyllys ch_rv = KMF_CheckCRLDate(kmfhandle, ¶ms); 238*3089Swyllys 239*3089Swyllys } else { /* certificate */ 240*3089Swyllys ch_rv = KMF_ReadInputFile(kmfhandle, fullpath, &cert); 241*3089Swyllys if (ch_rv != KMF_OK) 242*3089Swyllys goto end; 243*3089Swyllys 244*3089Swyllys if (format == KMF_FORMAT_PEM) { 245*3089Swyllys int len; 246*3089Swyllys ch_rv = KMF_Pem2Der(cert.Data, cert.Length, 247*3089Swyllys &cert_der.Data, &len); 248*3089Swyllys if (ch_rv != KMF_OK) 249*3089Swyllys goto end; 250*3089Swyllys cert_der.Length = (size_t)len; 251*3089Swyllys } 252*3089Swyllys 253*3089Swyllys ch_rv = KMF_CheckCertDate(kmfhandle, 254*3089Swyllys format == KMF_FORMAT_ASN1 ? &cert : &cert_der); 255*3089Swyllys } 256*3089Swyllys 257*3089Swyllys end: 258*3089Swyllys if (ch_rv == KMF_ERR_VALIDITY_PERIOD) { 259*3089Swyllys cryptoerror(LOG_STDERR, 260*3089Swyllys gettext("Warning: the downloaded file is expired.\n")); 261*3089Swyllys } else if (ch_rv != KMF_OK) { 262*3089Swyllys cryptoerror(LOG_STDERR, 263*3089Swyllys gettext("Warning: failed to check the validity.\n")); 264*3089Swyllys } 265*3089Swyllys 266*3089Swyllys if (fullpath) 267*3089Swyllys free(fullpath); 268*3089Swyllys 269*3089Swyllys KMF_FreeData(&cert); 270*3089Swyllys KMF_FreeData(&cert_der); 271*3089Swyllys 272*3089Swyllys (void) KMF_Finalize(kmfhandle); 273*3089Swyllys return (rv); 274*3089Swyllys } 275