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