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