17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5b5a2d845SHai-May Chao * Common Development and Distribution License (the "License").
6b5a2d845SHai-May Chao * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22b5a2d845SHai-May Chao * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
26bbbb143bSmcpowers #include <ctype.h>
277c478bd9Sstevel@tonic-gate #include <strings.h>
28b5a2d845SHai-May Chao #include <libintl.h>
29b5a2d845SHai-May Chao #include <stdio.h>
30b5a2d845SHai-May Chao #include <sys/stat.h>
317c478bd9Sstevel@tonic-gate #include "cryptoadm.h"
32b5a2d845SHai-May Chao #include <cryptoutil.h>
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate * Create one item of type mechlist_t with the mechanism name. A null is
367c478bd9Sstevel@tonic-gate * returned to indicate that the storage space available is insufficient.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate mechlist_t *
create_mech(char * name)397c478bd9Sstevel@tonic-gate create_mech(char *name)
407c478bd9Sstevel@tonic-gate {
417c478bd9Sstevel@tonic-gate mechlist_t *pres = NULL;
42bbbb143bSmcpowers char *first, *last;
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate if (name == NULL) {
457c478bd9Sstevel@tonic-gate return (NULL);
467c478bd9Sstevel@tonic-gate }
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate pres = malloc(sizeof (mechlist_t));
497c478bd9Sstevel@tonic-gate if (pres == NULL) {
507c478bd9Sstevel@tonic-gate cryptodebug("out of memory.");
517c478bd9Sstevel@tonic-gate return (NULL);
527c478bd9Sstevel@tonic-gate }
537c478bd9Sstevel@tonic-gate
54bbbb143bSmcpowers first = name;
55bbbb143bSmcpowers while (isspace(*first)) /* nuke leading whitespace */
56b5a2d845SHai-May Chao first++;
57bbbb143bSmcpowers (void) strlcpy(pres->name, first, sizeof (pres->name));
58bbbb143bSmcpowers
59bbbb143bSmcpowers last = strrchr(pres->name, '\0');
60bbbb143bSmcpowers last--;
61bbbb143bSmcpowers while (isspace(*last)) /* nuke trailing whitespace */
62b5a2d845SHai-May Chao *last-- = '\0';
63bbbb143bSmcpowers
647c478bd9Sstevel@tonic-gate pres->next = NULL;
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate return (pres);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate void
free_mechlist(mechlist_t * plist)727c478bd9Sstevel@tonic-gate free_mechlist(mechlist_t *plist)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate mechlist_t *pnext;
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate while (plist != NULL) {
777c478bd9Sstevel@tonic-gate pnext = plist->next;
787c478bd9Sstevel@tonic-gate free(plist);
797c478bd9Sstevel@tonic-gate plist = pnext;
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate * Check if the mechanism is in the mechanism list.
877c478bd9Sstevel@tonic-gate */
887c478bd9Sstevel@tonic-gate boolean_t
is_in_list(char * mechname,mechlist_t * plist)897c478bd9Sstevel@tonic-gate is_in_list(char *mechname, mechlist_t *plist)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE;
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate if (mechname == NULL) {
947c478bd9Sstevel@tonic-gate return (B_FALSE);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate while (plist != NULL) {
987c478bd9Sstevel@tonic-gate if (strcmp(plist->name, mechname) == 0) {
997c478bd9Sstevel@tonic-gate found = B_TRUE;
1007c478bd9Sstevel@tonic-gate break;
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate plist = plist->next;
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate return (found);
1067c478bd9Sstevel@tonic-gate }
107b5a2d845SHai-May Chao
108b5a2d845SHai-May Chao int
update_conf(char * conf_file,char * entry)109b5a2d845SHai-May Chao update_conf(char *conf_file, char *entry)
110b5a2d845SHai-May Chao {
111b5a2d845SHai-May Chao
112b5a2d845SHai-May Chao boolean_t found;
113*d616ad8eSHai-May Chao boolean_t fips_entry = B_FALSE;
114b5a2d845SHai-May Chao FILE *pfile;
115b5a2d845SHai-May Chao FILE *pfile_tmp;
116b5a2d845SHai-May Chao char tmpfile_name[MAXPATHLEN];
117b5a2d845SHai-May Chao char *ptr;
118b5a2d845SHai-May Chao char *name;
119b5a2d845SHai-May Chao char buffer[BUFSIZ];
120b5a2d845SHai-May Chao char buffer2[BUFSIZ];
121b5a2d845SHai-May Chao int found_count;
122b5a2d845SHai-May Chao int rc = SUCCESS;
123b5a2d845SHai-May Chao int err;
124b5a2d845SHai-May Chao
125b5a2d845SHai-May Chao if ((pfile = fopen(conf_file, "r+")) == NULL) {
126b5a2d845SHai-May Chao err = errno;
127b5a2d845SHai-May Chao cryptoerror(LOG_STDERR,
128b5a2d845SHai-May Chao gettext("failed to update the configuration - %s"),
129b5a2d845SHai-May Chao strerror(err));
130b5a2d845SHai-May Chao cryptodebug("failed to open %s for write.", conf_file);
131b5a2d845SHai-May Chao return (FAILURE);
132b5a2d845SHai-May Chao }
133b5a2d845SHai-May Chao
134b5a2d845SHai-May Chao if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
135b5a2d845SHai-May Chao err = errno;
136b5a2d845SHai-May Chao cryptoerror(LOG_STDERR,
137b5a2d845SHai-May Chao gettext("failed to lock the configuration - %s"),
138b5a2d845SHai-May Chao strerror(err));
139b5a2d845SHai-May Chao (void) fclose(pfile);
140b5a2d845SHai-May Chao return (FAILURE);
141b5a2d845SHai-May Chao }
142b5a2d845SHai-May Chao
143b5a2d845SHai-May Chao /*
144b5a2d845SHai-May Chao * Create a temporary file in the /etc/crypto directory.
145b5a2d845SHai-May Chao */
146b5a2d845SHai-May Chao (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
147b5a2d845SHai-May Chao if (mkstemp(tmpfile_name) == -1) {
148b5a2d845SHai-May Chao err = errno;
149b5a2d845SHai-May Chao cryptoerror(LOG_STDERR,
150b5a2d845SHai-May Chao gettext("failed to create a temporary file - %s"),
151b5a2d845SHai-May Chao strerror(err));
152b5a2d845SHai-May Chao (void) fclose(pfile);
153b5a2d845SHai-May Chao return (FAILURE);
154b5a2d845SHai-May Chao }
155b5a2d845SHai-May Chao
156b5a2d845SHai-May Chao if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
157b5a2d845SHai-May Chao err = errno;
158b5a2d845SHai-May Chao cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
159b5a2d845SHai-May Chao tmpfile_name, strerror(err));
160b5a2d845SHai-May Chao (void) fclose(pfile);
161b5a2d845SHai-May Chao return (FAILURE);
162b5a2d845SHai-May Chao }
163b5a2d845SHai-May Chao
164b5a2d845SHai-May Chao
165b5a2d845SHai-May Chao /*
166b5a2d845SHai-May Chao * Loop thru the config file. If the provider was reserved within a
167b5a2d845SHai-May Chao * package bracket, just uncomment it. Otherwise, append it at
168b5a2d845SHai-May Chao * the end. The resulting file will be saved in the temp file first.
169b5a2d845SHai-May Chao */
170b5a2d845SHai-May Chao found_count = 0;
171b5a2d845SHai-May Chao rc = SUCCESS;
172b5a2d845SHai-May Chao
173b5a2d845SHai-May Chao while (fgets(buffer, BUFSIZ, pfile) != NULL) {
174b5a2d845SHai-May Chao found = B_FALSE;
175b5a2d845SHai-May Chao if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) {
176b5a2d845SHai-May Chao if (buffer[0] == '#') {
177b5a2d845SHai-May Chao ptr = buffer;
178b5a2d845SHai-May Chao ptr++;
179b5a2d845SHai-May Chao if (strcmp(entry, ptr) == 0) {
180b5a2d845SHai-May Chao found = B_TRUE;
181b5a2d845SHai-May Chao found_count++;
182b5a2d845SHai-May Chao }
183*d616ad8eSHai-May Chao } else {
184*d616ad8eSHai-May Chao (void) strlcpy(buffer2, buffer, BUFSIZ);
185*d616ad8eSHai-May Chao ptr = buffer2;
186*d616ad8eSHai-May Chao if ((name = strtok(ptr, SEP_COLON)) == NULL) {
187*d616ad8eSHai-May Chao rc = FAILURE;
188*d616ad8eSHai-May Chao break;
189*d616ad8eSHai-May Chao } else if (strcmp(FIPS_KEYWORD, name) == 0) {
190*d616ad8eSHai-May Chao found = B_TRUE;
191*d616ad8eSHai-May Chao found_count++;
192*d616ad8eSHai-May Chao fips_entry = B_TRUE;
193*d616ad8eSHai-May Chao }
194b5a2d845SHai-May Chao }
195b5a2d845SHai-May Chao } else { /* _PATH_KCF_CONF */
196b5a2d845SHai-May Chao if (buffer[0] == '#') {
197b5a2d845SHai-May Chao (void) strlcpy(buffer2, buffer, BUFSIZ);
198b5a2d845SHai-May Chao ptr = buffer2;
199b5a2d845SHai-May Chao ptr++; /* skip # */
200b5a2d845SHai-May Chao if ((name = strtok(ptr, SEP_COLON)) == NULL) {
201b5a2d845SHai-May Chao rc = FAILURE;
202b5a2d845SHai-May Chao break;
203b5a2d845SHai-May Chao }
204b5a2d845SHai-May Chao } else {
205b5a2d845SHai-May Chao (void) strlcpy(buffer2, buffer, BUFSIZ);
206b5a2d845SHai-May Chao ptr = buffer2;
207b5a2d845SHai-May Chao if ((name = strtok(ptr, SEP_COLON)) == NULL) {
208b5a2d845SHai-May Chao rc = FAILURE;
209b5a2d845SHai-May Chao break;
210b5a2d845SHai-May Chao }
211b5a2d845SHai-May Chao }
212b5a2d845SHai-May Chao }
213b5a2d845SHai-May Chao
214b5a2d845SHai-May Chao if (found == B_FALSE) {
215b5a2d845SHai-May Chao if (fputs(buffer, pfile_tmp) == EOF) {
216b5a2d845SHai-May Chao rc = FAILURE;
217b5a2d845SHai-May Chao }
218b5a2d845SHai-May Chao } else {
219b5a2d845SHai-May Chao if (found_count == 1) {
220b5a2d845SHai-May Chao if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) {
221*d616ad8eSHai-May Chao if (fips_entry == B_TRUE) {
222*d616ad8eSHai-May Chao if (fputs(entry, pfile_tmp) ==
223*d616ad8eSHai-May Chao EOF) {
224*d616ad8eSHai-May Chao rc = FAILURE;
225*d616ad8eSHai-May Chao }
226*d616ad8eSHai-May Chao fips_entry = B_FALSE;
227*d616ad8eSHai-May Chao } else {
228*d616ad8eSHai-May Chao if (fputs(ptr, pfile_tmp) ==
229*d616ad8eSHai-May Chao EOF) {
230*d616ad8eSHai-May Chao rc = FAILURE;
231*d616ad8eSHai-May Chao }
232b5a2d845SHai-May Chao }
233b5a2d845SHai-May Chao } else {
234b5a2d845SHai-May Chao if (fputs(entry, pfile_tmp) == EOF) {
235b5a2d845SHai-May Chao rc = FAILURE;
236b5a2d845SHai-May Chao }
237b5a2d845SHai-May Chao }
238b5a2d845SHai-May Chao } else {
239b5a2d845SHai-May Chao /*
240b5a2d845SHai-May Chao * Found a second entry with same tag name.
241b5a2d845SHai-May Chao * Should not happen. The config file
242b5a2d845SHai-May Chao * is corrupted. Give a warning and skip
243b5a2d845SHai-May Chao * this entry.
244b5a2d845SHai-May Chao */
245b5a2d845SHai-May Chao cryptoerror(LOG_STDERR, gettext(
246b5a2d845SHai-May Chao "(Warning) Found an additional reserved "
247b5a2d845SHai-May Chao "entry for %s."), entry);
248b5a2d845SHai-May Chao }
249b5a2d845SHai-May Chao }
250b5a2d845SHai-May Chao
251b5a2d845SHai-May Chao if (rc == FAILURE) {
252b5a2d845SHai-May Chao break;
253b5a2d845SHai-May Chao }
254b5a2d845SHai-May Chao }
255b5a2d845SHai-May Chao
256b5a2d845SHai-May Chao (void) fclose(pfile);
257b5a2d845SHai-May Chao
258b5a2d845SHai-May Chao if (rc == FAILURE) {
259b5a2d845SHai-May Chao cryptoerror(LOG_STDERR, gettext("write error."));
260b5a2d845SHai-May Chao (void) fclose(pfile_tmp);
261b5a2d845SHai-May Chao if (unlink(tmpfile_name) != 0) {
262b5a2d845SHai-May Chao err = errno;
263b5a2d845SHai-May Chao cryptoerror(LOG_STDERR, gettext(
264b5a2d845SHai-May Chao "(Warning) failed to remove %s: %s"), tmpfile_name,
265b5a2d845SHai-May Chao strerror(err));
266b5a2d845SHai-May Chao }
267b5a2d845SHai-May Chao return (FAILURE);
268b5a2d845SHai-May Chao }
269b5a2d845SHai-May Chao
270b5a2d845SHai-May Chao if (found_count == 0) {
271b5a2d845SHai-May Chao /*
272b5a2d845SHai-May Chao * The entry was not in config file before, append it to the
273b5a2d845SHai-May Chao * end of the temp file.
274b5a2d845SHai-May Chao */
275b5a2d845SHai-May Chao if (fputs(entry, pfile_tmp) == EOF) {
276b5a2d845SHai-May Chao cryptoerror(LOG_STDERR, gettext(
277b5a2d845SHai-May Chao "failed to write to %s: %s"), tmpfile_name,
278b5a2d845SHai-May Chao strerror(errno));
279b5a2d845SHai-May Chao (void) fclose(pfile_tmp);
280b5a2d845SHai-May Chao if (unlink(tmpfile_name) != 0) {
281b5a2d845SHai-May Chao err = errno;
282b5a2d845SHai-May Chao cryptoerror(LOG_STDERR, gettext(
283b5a2d845SHai-May Chao "(Warning) failed to remove %s: %s"),
284b5a2d845SHai-May Chao tmpfile_name, strerror(err));
285b5a2d845SHai-May Chao }
286b5a2d845SHai-May Chao return (FAILURE);
287b5a2d845SHai-May Chao }
288b5a2d845SHai-May Chao }
289b5a2d845SHai-May Chao
290b5a2d845SHai-May Chao if (fclose(pfile_tmp) != 0) {
291b5a2d845SHai-May Chao err = errno;
292b5a2d845SHai-May Chao cryptoerror(LOG_STDERR,
293b5a2d845SHai-May Chao gettext("failed to close %s: %s"), tmpfile_name,
294b5a2d845SHai-May Chao strerror(err));
295b5a2d845SHai-May Chao return (FAILURE);
296b5a2d845SHai-May Chao }
297b5a2d845SHai-May Chao
298b5a2d845SHai-May Chao if (rename(tmpfile_name, conf_file) == -1) {
299b5a2d845SHai-May Chao err = errno;
300b5a2d845SHai-May Chao cryptoerror(LOG_STDERR,
301b5a2d845SHai-May Chao gettext("failed to update the configuration - %s"),
302b5a2d845SHai-May Chao strerror(err));
303b5a2d845SHai-May Chao cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
304b5a2d845SHai-May Chao conf_file, strerror(err));
305b5a2d845SHai-May Chao rc = FAILURE;
306b5a2d845SHai-May Chao } else if (chmod(conf_file,
307b5a2d845SHai-May Chao S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
308b5a2d845SHai-May Chao err = errno;
309b5a2d845SHai-May Chao cryptoerror(LOG_STDERR,
310b5a2d845SHai-May Chao gettext("failed to update the configuration - %s"),
311b5a2d845SHai-May Chao strerror(err));
312b5a2d845SHai-May Chao cryptodebug("failed to chmod to %s: %s", conf_file,
313b5a2d845SHai-May Chao strerror(err));
314b5a2d845SHai-May Chao rc = FAILURE;
315b5a2d845SHai-May Chao } else {
316b5a2d845SHai-May Chao rc = SUCCESS;
317b5a2d845SHai-May Chao }
318b5a2d845SHai-May Chao
319b5a2d845SHai-May Chao if (rc == FAILURE) {
320b5a2d845SHai-May Chao if (unlink(tmpfile_name) != 0) {
321b5a2d845SHai-May Chao err = errno;
322b5a2d845SHai-May Chao cryptoerror(LOG_STDERR, gettext(
323b5a2d845SHai-May Chao "(Warning) failed to remove %s: %s"),
324b5a2d845SHai-May Chao tmpfile_name, strerror(err));
325b5a2d845SHai-May Chao }
326b5a2d845SHai-May Chao }
327b5a2d845SHai-May Chao
328b5a2d845SHai-May Chao return (rc);
329b5a2d845SHai-May Chao
330b5a2d845SHai-May Chao }
331