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