1*431deaa0Shylee /* 2*431deaa0Shylee * CDDL HEADER START 3*431deaa0Shylee * 4*431deaa0Shylee * The contents of this file are subject to the terms of the 5*431deaa0Shylee * Common Development and Distribution License (the "License"). 6*431deaa0Shylee * You may not use this file except in compliance with the License. 7*431deaa0Shylee * 8*431deaa0Shylee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*431deaa0Shylee * or http://www.opensolaris.org/os/licensing. 10*431deaa0Shylee * See the License for the specific language governing permissions 11*431deaa0Shylee * and limitations under the License. 12*431deaa0Shylee * 13*431deaa0Shylee * When distributing Covered Code, include this CDDL HEADER in each 14*431deaa0Shylee * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*431deaa0Shylee * If applicable, add the following below this CDDL HEADER, with the 16*431deaa0Shylee * fields enclosed by brackets "[]" replaced with your own identifying 17*431deaa0Shylee * information: Portions Copyright [yyyy] [name of copyright owner] 18*431deaa0Shylee * 19*431deaa0Shylee * CDDL HEADER END 20*431deaa0Shylee * 21*431deaa0Shylee * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 22*431deaa0Shylee * Use is subject to license terms. 23*431deaa0Shylee */ 24*431deaa0Shylee 25*431deaa0Shylee #pragma ident "%Z%%M% %I% %E% SMI" 26*431deaa0Shylee 27*431deaa0Shylee #include <stdio.h> 28*431deaa0Shylee #include <strings.h> 29*431deaa0Shylee #include <ctype.h> 30*431deaa0Shylee #include <libgen.h> 31*431deaa0Shylee #include <libintl.h> 32*431deaa0Shylee #include <errno.h> 33*431deaa0Shylee #include <kmfapiP.h> 34*431deaa0Shylee #include <sys/stat.h> 35*431deaa0Shylee #include <sys/param.h> 36*431deaa0Shylee #include <cryptoutil.h> 37*431deaa0Shylee #include "util.h" 38*431deaa0Shylee 39*431deaa0Shylee static int err; /* To store errno which may be overwritten by gettext() */ 40*431deaa0Shylee 41*431deaa0Shylee int 42*431deaa0Shylee kc_install(int argc, char *argv[]) 43*431deaa0Shylee { 44*431deaa0Shylee int rv = KC_OK; 45*431deaa0Shylee int opt; 46*431deaa0Shylee extern int optind_av; 47*431deaa0Shylee extern char *optarg_av; 48*431deaa0Shylee char *keystore_name = NULL; 49*431deaa0Shylee char *modulepath = NULL; 50*431deaa0Shylee char *option_str = NULL; 51*431deaa0Shylee conf_entry_t *entry = NULL; 52*431deaa0Shylee char realpath[MAXPATHLEN]; 53*431deaa0Shylee struct stat statbuf; 54*431deaa0Shylee FILE *pfile = NULL; 55*431deaa0Shylee FILE *pfile_tmp = NULL; 56*431deaa0Shylee char tmpfile_name[MAXPATHLEN]; 57*431deaa0Shylee int found_count = 0; 58*431deaa0Shylee char buffer[BUFSIZ]; 59*431deaa0Shylee char *ptr; 60*431deaa0Shylee boolean_t found; 61*431deaa0Shylee 62*431deaa0Shylee while ((opt = getopt_av(argc, argv, "k:(keystore)m:(modulepath)" 63*431deaa0Shylee "o:(option)")) != EOF) { 64*431deaa0Shylee switch (opt) { 65*431deaa0Shylee case 'k': 66*431deaa0Shylee if (keystore_name != NULL) 67*431deaa0Shylee rv = KC_ERR_USAGE; 68*431deaa0Shylee else { 69*431deaa0Shylee keystore_name = get_string(optarg_av, &rv); 70*431deaa0Shylee if (keystore_name == NULL) { 71*431deaa0Shylee (void) fprintf(stderr, gettext( 72*431deaa0Shylee "Error keystore input.\n")); 73*431deaa0Shylee } 74*431deaa0Shylee } 75*431deaa0Shylee break; 76*431deaa0Shylee case 'm': 77*431deaa0Shylee if (modulepath != NULL) 78*431deaa0Shylee rv = KC_ERR_USAGE; 79*431deaa0Shylee else { 80*431deaa0Shylee modulepath = get_string(optarg_av, &rv); 81*431deaa0Shylee if (modulepath == NULL) { 82*431deaa0Shylee (void) fprintf(stderr, 83*431deaa0Shylee gettext("Error modulepath.\n")); 84*431deaa0Shylee } 85*431deaa0Shylee } 86*431deaa0Shylee break; 87*431deaa0Shylee case 'o': 88*431deaa0Shylee if (option_str != NULL) { 89*431deaa0Shylee rv = KC_ERR_USAGE; 90*431deaa0Shylee } else { 91*431deaa0Shylee option_str = get_string(optarg_av, &rv); 92*431deaa0Shylee if (option_str == NULL) { 93*431deaa0Shylee (void) fprintf(stderr, 94*431deaa0Shylee gettext("Error option input.\n")); 95*431deaa0Shylee } 96*431deaa0Shylee } 97*431deaa0Shylee break; 98*431deaa0Shylee default: 99*431deaa0Shylee (void) fprintf(stderr, 100*431deaa0Shylee gettext("Error input option.\n")); 101*431deaa0Shylee rv = KC_ERR_USAGE; 102*431deaa0Shylee break; 103*431deaa0Shylee } 104*431deaa0Shylee if (rv != KC_OK) 105*431deaa0Shylee goto out; 106*431deaa0Shylee } 107*431deaa0Shylee 108*431deaa0Shylee /* No additional args allowed. */ 109*431deaa0Shylee argc -= optind_av; 110*431deaa0Shylee if (argc) { 111*431deaa0Shylee (void) fprintf(stderr, 112*431deaa0Shylee gettext("Error input option\n")); 113*431deaa0Shylee rv = KC_ERR_USAGE; 114*431deaa0Shylee goto out; 115*431deaa0Shylee } 116*431deaa0Shylee 117*431deaa0Shylee if (keystore_name == NULL || modulepath == NULL) { 118*431deaa0Shylee (void) fprintf(stderr, gettext("Error input option\n")); 119*431deaa0Shylee rv = KC_ERR_USAGE; 120*431deaa0Shylee goto out; 121*431deaa0Shylee } 122*431deaa0Shylee 123*431deaa0Shylee if (strcasecmp(keystore_name, "nss") == 0 || 124*431deaa0Shylee strcasecmp(keystore_name, "pkcs11") == 0 || 125*431deaa0Shylee strcasecmp(keystore_name, "file") == 0) { 126*431deaa0Shylee (void) fprintf(stderr, 127*431deaa0Shylee gettext("Can not use the built-in keystore name %s\n"), 128*431deaa0Shylee keystore_name); 129*431deaa0Shylee rv = KC_ERR_USAGE; 130*431deaa0Shylee goto out; 131*431deaa0Shylee } 132*431deaa0Shylee 133*431deaa0Shylee entry = get_keystore_entry(keystore_name); 134*431deaa0Shylee if (entry != NULL) { 135*431deaa0Shylee (void) fprintf(stderr, gettext("%s exists already.\n"), 136*431deaa0Shylee keystore_name); 137*431deaa0Shylee rv = KC_ERR_USAGE; 138*431deaa0Shylee goto out; 139*431deaa0Shylee } 140*431deaa0Shylee 141*431deaa0Shylee /* 142*431deaa0Shylee * Find the absolute path of the module and check if it exists in 143*431deaa0Shylee * the system. If $ISA is in the path, will check the 32bit version 144*431deaa0Shylee * only. 145*431deaa0Shylee */ 146*431deaa0Shylee if (strncmp(modulepath, "/", 1) != 0) { 147*431deaa0Shylee /* 148*431deaa0Shylee * Only contain the base name; prepand it with 149*431deaa0Shylee * KMF_PLUGIN_PATH 150*431deaa0Shylee */ 151*431deaa0Shylee (void) snprintf(realpath, MAXPATHLEN, "%s%s", 152*431deaa0Shylee KMF_PLUGIN_PATH, modulepath); 153*431deaa0Shylee } else { 154*431deaa0Shylee char *buf = modulepath; 155*431deaa0Shylee char *isa; 156*431deaa0Shylee 157*431deaa0Shylee if ((isa = strstr(buf, PKCS11_ISA)) != NULL) { 158*431deaa0Shylee (void) strncpy(realpath, buf, isa - buf); 159*431deaa0Shylee isa += strlen(PKCS11_ISA) - 1; 160*431deaa0Shylee (void) strlcat(realpath, isa, MAXPATHLEN); 161*431deaa0Shylee } else { 162*431deaa0Shylee (void) strlcpy(realpath, modulepath, MAXPATHLEN); 163*431deaa0Shylee } 164*431deaa0Shylee } 165*431deaa0Shylee 166*431deaa0Shylee if (stat(realpath, &statbuf) != 0) { 167*431deaa0Shylee (void) fprintf(stderr, gettext("%s not found.\n"), 168*431deaa0Shylee realpath); 169*431deaa0Shylee rv = KC_ERR_ACCESS; 170*431deaa0Shylee goto out; 171*431deaa0Shylee } 172*431deaa0Shylee 173*431deaa0Shylee if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) { 174*431deaa0Shylee err = errno; 175*431deaa0Shylee (void) fprintf(stderr, 176*431deaa0Shylee gettext("failed to update the configuration - %s\n"), 177*431deaa0Shylee strerror(err)); 178*431deaa0Shylee rv = KC_ERR_ACCESS; 179*431deaa0Shylee goto out; 180*431deaa0Shylee } 181*431deaa0Shylee 182*431deaa0Shylee if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 183*431deaa0Shylee err = errno; 184*431deaa0Shylee (void) fprintf(stderr, 185*431deaa0Shylee gettext("failed to lock the configuration - %s\n"), 186*431deaa0Shylee strerror(err)); 187*431deaa0Shylee rv = KC_ERR_INSTALL; 188*431deaa0Shylee goto out; 189*431deaa0Shylee } 190*431deaa0Shylee 191*431deaa0Shylee /* 192*431deaa0Shylee * Create a temporary file in the /etc/crypto directory. 193*431deaa0Shylee */ 194*431deaa0Shylee (void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name)); 195*431deaa0Shylee if (mkstemp(tmpfile_name) == -1) { 196*431deaa0Shylee err = errno; 197*431deaa0Shylee (void) fprintf(stderr, 198*431deaa0Shylee gettext("failed to create a temporary file - %s\n"), 199*431deaa0Shylee strerror(err)); 200*431deaa0Shylee rv = KC_ERR_INSTALL; 201*431deaa0Shylee goto out; 202*431deaa0Shylee } 203*431deaa0Shylee 204*431deaa0Shylee if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 205*431deaa0Shylee err = errno; 206*431deaa0Shylee (void) fprintf(stderr, 207*431deaa0Shylee gettext("failed to open %s - %s\n"), 208*431deaa0Shylee tmpfile_name, strerror(err)); 209*431deaa0Shylee rv = KC_ERR_INSTALL; 210*431deaa0Shylee goto out; 211*431deaa0Shylee } 212*431deaa0Shylee 213*431deaa0Shylee /* 214*431deaa0Shylee * Loop thru the config file. If the file was reserved within a 215*431deaa0Shylee * package bracket, just uncomment it. Other wise, append it at 216*431deaa0Shylee * the end. The resulting file will be saved in the temp file first. 217*431deaa0Shylee */ 218*431deaa0Shylee while (fgets(buffer, BUFSIZ, pfile) != NULL) { 219*431deaa0Shylee found = B_FALSE; 220*431deaa0Shylee if (buffer[0] == '#') { 221*431deaa0Shylee ptr = buffer; 222*431deaa0Shylee ptr++; 223*431deaa0Shylee while (*ptr == '#' || *ptr == ' ') 224*431deaa0Shylee ptr++; 225*431deaa0Shylee if (strncmp(keystore_name, ptr, strlen(keystore_name)) 226*431deaa0Shylee == 0) { 227*431deaa0Shylee found = B_TRUE; 228*431deaa0Shylee found_count++; 229*431deaa0Shylee } 230*431deaa0Shylee } 231*431deaa0Shylee 232*431deaa0Shylee if (found == B_FALSE) { 233*431deaa0Shylee if (fputs(buffer, pfile_tmp) == EOF) { 234*431deaa0Shylee rv = KC_ERR_INSTALL; 235*431deaa0Shylee goto out; 236*431deaa0Shylee } 237*431deaa0Shylee } else { 238*431deaa0Shylee if (found_count == 1) { 239*431deaa0Shylee if (fputs(ptr, pfile_tmp) == EOF) { 240*431deaa0Shylee rv = KC_ERR_INSTALL; 241*431deaa0Shylee goto out; 242*431deaa0Shylee } 243*431deaa0Shylee } else { 244*431deaa0Shylee /* 245*431deaa0Shylee * Found a second entry with #keystore_name. 246*431deaa0Shylee * This should not happen. The kmf.conf file 247*431deaa0Shylee * is corrupted. Give a warning and skip 248*431deaa0Shylee * this entry. 249*431deaa0Shylee */ 250*431deaa0Shylee (void) fprintf(stderr, gettext( 251*431deaa0Shylee "(Warning) Found an additional reserved " 252*431deaa0Shylee "entry for %s.\n"), keystore_name); 253*431deaa0Shylee } 254*431deaa0Shylee } 255*431deaa0Shylee } 256*431deaa0Shylee 257*431deaa0Shylee if (found_count == 0) { 258*431deaa0Shylee char buf[MAXPATHLEN]; 259*431deaa0Shylee /* 260*431deaa0Shylee * This entry was not in package before, append it to the 261*431deaa0Shylee * end of the temp file. 262*431deaa0Shylee */ 263*431deaa0Shylee if (option_str == NULL) 264*431deaa0Shylee (void) snprintf(buf, MAXPATHLEN, "%s:%s%s\n", 265*431deaa0Shylee keystore_name, CONF_MODULEPATH, modulepath); 266*431deaa0Shylee else 267*431deaa0Shylee (void) snprintf(buf, MAXPATHLEN, "%s:%s%s;%s%s\n", 268*431deaa0Shylee keystore_name, CONF_MODULEPATH, modulepath, 269*431deaa0Shylee CONF_OPTION, option_str); 270*431deaa0Shylee 271*431deaa0Shylee if (fputs(buf, pfile_tmp) == EOF) { 272*431deaa0Shylee err = errno; 273*431deaa0Shylee (void) fprintf(stderr, gettext( 274*431deaa0Shylee "failed to write to %s: %s\n"), tmpfile_name, 275*431deaa0Shylee strerror(err)); 276*431deaa0Shylee rv = KC_ERR_INSTALL; 277*431deaa0Shylee goto out; 278*431deaa0Shylee } 279*431deaa0Shylee } 280*431deaa0Shylee 281*431deaa0Shylee out: 282*431deaa0Shylee if (pfile != NULL) 283*431deaa0Shylee (void) fclose(pfile); 284*431deaa0Shylee 285*431deaa0Shylee if (rv != KC_OK && pfile_tmp != NULL) 286*431deaa0Shylee (void) unlink(tmpfile_name); 287*431deaa0Shylee 288*431deaa0Shylee if (pfile_tmp != NULL) 289*431deaa0Shylee (void) fclose(pfile_tmp); 290*431deaa0Shylee 291*431deaa0Shylee if (rv == KC_OK) { 292*431deaa0Shylee if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) { 293*431deaa0Shylee err = errno; 294*431deaa0Shylee (void) fprintf(stderr, gettext( 295*431deaa0Shylee "failed to update the configuration - %s"), 296*431deaa0Shylee strerror(err)); 297*431deaa0Shylee return (KC_ERR_INSTALL); 298*431deaa0Shylee } 299*431deaa0Shylee 300*431deaa0Shylee if (chmod(_PATH_KMF_CONF, 301*431deaa0Shylee S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 302*431deaa0Shylee err = errno; 303*431deaa0Shylee (void) fprintf(stderr, gettext( 304*431deaa0Shylee "failed to update the configuration - %s\n"), 305*431deaa0Shylee strerror(err)); 306*431deaa0Shylee return (KC_ERR_INSTALL); 307*431deaa0Shylee } 308*431deaa0Shylee } 309*431deaa0Shylee 310*431deaa0Shylee return (rv); 311*431deaa0Shylee } 312