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_uninstall(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 conf_entry_t *entry = NULL; 48 FILE *pfile = NULL; 49 FILE *pfile_tmp = NULL; 50 char tmpfile_name[MAXPATHLEN]; 51 char buffer[MAXPATHLEN]; 52 char buffer2[MAXPATHLEN]; 53 boolean_t found; 54 boolean_t in_package; 55 56 while ((opt = getopt_av(argc, argv, "k:(keystore)")) != EOF) { 57 switch (opt) { 58 case 'k': 59 if (keystore_name != NULL) 60 rv = KC_ERR_USAGE; 61 else { 62 keystore_name = get_string(optarg_av, &rv); 63 if (keystore_name == NULL) { 64 (void) fprintf(stderr, gettext( 65 "Error keystore input.\n")); 66 } 67 } 68 break; 69 default: 70 (void) fprintf(stderr, 71 gettext("Error input option.\n")); 72 rv = KC_ERR_USAGE; 73 break; 74 } 75 if (rv != KC_OK) 76 goto out; 77 } 78 79 /* No additional args allowed. */ 80 argc -= optind_av; 81 if (argc) { 82 (void) fprintf(stderr, 83 gettext("Error input option\n")); 84 rv = KC_ERR_USAGE; 85 goto out; 86 } 87 88 if (keystore_name == NULL) { 89 (void) fprintf(stderr, 90 gettext("Error input option\n")); 91 rv = KC_ERR_USAGE; 92 goto out; 93 } 94 95 if (strcasecmp(keystore_name, "nss") == 0 || 96 strcasecmp(keystore_name, "pkcs11") == 0 || 97 strcasecmp(keystore_name, "file") == 0) { 98 (void) fprintf(stderr, 99 gettext("Can not uninstall the built-in keystore %s\n"), 100 keystore_name); 101 rv = KC_ERR_UNINSTALL; 102 goto out; 103 } 104 105 entry = get_keystore_entry(keystore_name); 106 if (entry == NULL) { 107 (void) fprintf(stderr, gettext("%s does not exist.\n"), 108 keystore_name); 109 rv = KC_ERR_USAGE; 110 goto out; 111 } 112 113 if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) { 114 err = errno; 115 (void) fprintf(stderr, 116 gettext("failed to update the configuration - %s\n"), 117 strerror(err)); 118 rv = KC_ERR_ACCESS; 119 goto out; 120 } 121 122 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 123 err = errno; 124 (void) fprintf(stderr, 125 gettext("failed to lock the configuration - %s\n"), 126 strerror(err)); 127 rv = KC_ERR_UNINSTALL; 128 goto out; 129 } 130 131 /* 132 * Create a temporary file in the /etc/crypto directory. 133 */ 134 (void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name)); 135 if (mkstemp(tmpfile_name) == -1) { 136 err = errno; 137 (void) fprintf(stderr, 138 gettext("failed to create a temporary file - %s\n"), 139 strerror(err)); 140 rv = KC_ERR_UNINSTALL; 141 goto out; 142 } 143 144 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 145 err = errno; 146 (void) fprintf(stderr, 147 gettext("failed to open a temporary file - %s\n"), 148 strerror(err)); 149 rv = KC_ERR_UNINSTALL; 150 goto out; 151 } 152 153 /* 154 * Loop thru the config file. If the plugin to be uninstalled is in 155 * a package, then just comment it off. 156 */ 157 in_package = B_FALSE; 158 while (fgets(buffer, MAXPATHLEN, pfile) != NULL) { 159 found = B_FALSE; 160 if (buffer[0] != ' ' && buffer[0] != '\n' && 161 buffer[0] != '\t') { 162 if (strstr(buffer, " Start ") != NULL) { 163 in_package = B_TRUE; 164 } else if (strstr(buffer, " End ") != NULL) { 165 in_package = B_FALSE; 166 } else if (buffer[0] != '#') { 167 char *name; 168 int len; 169 170 /* 171 * make a copy of the original buffer to 172 * buffer2. Also get rid of the trailing 173 * '\n' from buffer2. 174 */ 175 (void) strlcpy(buffer2, buffer, MAXPATHLEN); 176 /* get rid of trailing '\n' */ 177 len = strlen(buffer2); 178 if (buffer2[len-1] == '\n') { 179 len--; 180 } 181 buffer2[len] = '\0'; 182 183 if ((name = strtok(buffer2, SEP_COLON)) == 184 NULL) { 185 rv = KC_ERR_UNINSTALL; 186 goto out; 187 } 188 189 if (strcmp(keystore_name, name) == 0) 190 found = B_TRUE; 191 } 192 } 193 194 if (found) { 195 /* 196 * If found and not in_package, then don't write 197 * this line to the result file. 198 */ 199 if (in_package) { 200 (void) snprintf(buffer2, sizeof (buffer2), 201 "%s%s", "#", buffer); 202 203 if (fputs(buffer2, pfile_tmp) == EOF) { 204 rv = KC_ERR_UNINSTALL; 205 goto out; 206 } 207 } 208 } else { 209 if (fputs(buffer, pfile_tmp) == EOF) { 210 rv = KC_ERR_UNINSTALL; 211 goto out; 212 } 213 } 214 } 215 216 out: 217 if (pfile != NULL) 218 (void) fclose(pfile); 219 220 if (rv != KC_OK && pfile_tmp != NULL) 221 (void) unlink(tmpfile_name); 222 223 if (pfile_tmp != NULL) 224 (void) fclose(pfile_tmp); 225 226 if (rv == KC_OK) { 227 if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) { 228 err = errno; 229 (void) fprintf(stderr, gettext( 230 "failed to update the configuration - %s"), 231 strerror(err)); 232 return (KC_ERR_UNINSTALL); 233 } 234 235 if (chmod(_PATH_KMF_CONF, 236 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 237 err = errno; 238 (void) fprintf(stderr, gettext( 239 "failed to update the configuration - %s\n"), 240 strerror(err)); 241 return (KC_ERR_UNINSTALL); 242 } 243 } 244 245 return (rv); 246 } 247