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
kc_uninstall(int argc,char * argv[])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