10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
510500SHai-May.Chao@Sun.COM * Common Development and Distribution License (the "License").
610500SHai-May.Chao@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
2210500SHai-May.Chao@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
26991Smcpowers #include <ctype.h>
270Sstevel@tonic-gate #include <strings.h>
2810500SHai-May.Chao@Sun.COM #include <libintl.h>
2910500SHai-May.Chao@Sun.COM #include <stdio.h>
3010500SHai-May.Chao@Sun.COM #include <sys/stat.h>
310Sstevel@tonic-gate #include "cryptoadm.h"
3210500SHai-May.Chao@Sun.COM #include <cryptoutil.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate * Create one item of type mechlist_t with the mechanism name. A null is
360Sstevel@tonic-gate * returned to indicate that the storage space available is insufficient.
370Sstevel@tonic-gate */
380Sstevel@tonic-gate mechlist_t *
create_mech(char * name)390Sstevel@tonic-gate create_mech(char *name)
400Sstevel@tonic-gate {
410Sstevel@tonic-gate mechlist_t *pres = NULL;
42991Smcpowers char *first, *last;
430Sstevel@tonic-gate
440Sstevel@tonic-gate if (name == NULL) {
450Sstevel@tonic-gate return (NULL);
460Sstevel@tonic-gate }
470Sstevel@tonic-gate
480Sstevel@tonic-gate pres = malloc(sizeof (mechlist_t));
490Sstevel@tonic-gate if (pres == NULL) {
500Sstevel@tonic-gate cryptodebug("out of memory.");
510Sstevel@tonic-gate return (NULL);
520Sstevel@tonic-gate }
530Sstevel@tonic-gate
54991Smcpowers first = name;
55991Smcpowers while (isspace(*first)) /* nuke leading whitespace */
5610500SHai-May.Chao@Sun.COM first++;
57991Smcpowers (void) strlcpy(pres->name, first, sizeof (pres->name));
58991Smcpowers
59991Smcpowers last = strrchr(pres->name, '\0');
60991Smcpowers last--;
61991Smcpowers while (isspace(*last)) /* nuke trailing whitespace */
6210500SHai-May.Chao@Sun.COM *last-- = '\0';
63991Smcpowers
640Sstevel@tonic-gate pres->next = NULL;
650Sstevel@tonic-gate
660Sstevel@tonic-gate return (pres);
670Sstevel@tonic-gate }
680Sstevel@tonic-gate
690Sstevel@tonic-gate
700Sstevel@tonic-gate
710Sstevel@tonic-gate void
free_mechlist(mechlist_t * plist)720Sstevel@tonic-gate free_mechlist(mechlist_t *plist)
730Sstevel@tonic-gate {
740Sstevel@tonic-gate mechlist_t *pnext;
750Sstevel@tonic-gate
760Sstevel@tonic-gate while (plist != NULL) {
770Sstevel@tonic-gate pnext = plist->next;
780Sstevel@tonic-gate free(plist);
790Sstevel@tonic-gate plist = pnext;
800Sstevel@tonic-gate }
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate
840Sstevel@tonic-gate
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate * Check if the mechanism is in the mechanism list.
870Sstevel@tonic-gate */
880Sstevel@tonic-gate boolean_t
is_in_list(char * mechname,mechlist_t * plist)890Sstevel@tonic-gate is_in_list(char *mechname, mechlist_t *plist)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate boolean_t found = B_FALSE;
920Sstevel@tonic-gate
930Sstevel@tonic-gate if (mechname == NULL) {
940Sstevel@tonic-gate return (B_FALSE);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate while (plist != NULL) {
980Sstevel@tonic-gate if (strcmp(plist->name, mechname) == 0) {
990Sstevel@tonic-gate found = B_TRUE;
1000Sstevel@tonic-gate break;
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate plist = plist->next;
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate return (found);
1060Sstevel@tonic-gate }
10710500SHai-May.Chao@Sun.COM
10810500SHai-May.Chao@Sun.COM int
update_conf(char * conf_file,char * entry)10910500SHai-May.Chao@Sun.COM update_conf(char *conf_file, char *entry)
11010500SHai-May.Chao@Sun.COM {
11110500SHai-May.Chao@Sun.COM
11210500SHai-May.Chao@Sun.COM boolean_t found;
113*10979SHai-May.Chao@Sun.COM boolean_t fips_entry = B_FALSE;
11410500SHai-May.Chao@Sun.COM FILE *pfile;
11510500SHai-May.Chao@Sun.COM FILE *pfile_tmp;
11610500SHai-May.Chao@Sun.COM char tmpfile_name[MAXPATHLEN];
11710500SHai-May.Chao@Sun.COM char *ptr;
11810500SHai-May.Chao@Sun.COM char *name;
11910500SHai-May.Chao@Sun.COM char buffer[BUFSIZ];
12010500SHai-May.Chao@Sun.COM char buffer2[BUFSIZ];
12110500SHai-May.Chao@Sun.COM int found_count;
12210500SHai-May.Chao@Sun.COM int rc = SUCCESS;
12310500SHai-May.Chao@Sun.COM int err;
12410500SHai-May.Chao@Sun.COM
12510500SHai-May.Chao@Sun.COM if ((pfile = fopen(conf_file, "r+")) == NULL) {
12610500SHai-May.Chao@Sun.COM err = errno;
12710500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR,
12810500SHai-May.Chao@Sun.COM gettext("failed to update the configuration - %s"),
12910500SHai-May.Chao@Sun.COM strerror(err));
13010500SHai-May.Chao@Sun.COM cryptodebug("failed to open %s for write.", conf_file);
13110500SHai-May.Chao@Sun.COM return (FAILURE);
13210500SHai-May.Chao@Sun.COM }
13310500SHai-May.Chao@Sun.COM
13410500SHai-May.Chao@Sun.COM if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
13510500SHai-May.Chao@Sun.COM err = errno;
13610500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR,
13710500SHai-May.Chao@Sun.COM gettext("failed to lock the configuration - %s"),
13810500SHai-May.Chao@Sun.COM strerror(err));
13910500SHai-May.Chao@Sun.COM (void) fclose(pfile);
14010500SHai-May.Chao@Sun.COM return (FAILURE);
14110500SHai-May.Chao@Sun.COM }
14210500SHai-May.Chao@Sun.COM
14310500SHai-May.Chao@Sun.COM /*
14410500SHai-May.Chao@Sun.COM * Create a temporary file in the /etc/crypto directory.
14510500SHai-May.Chao@Sun.COM */
14610500SHai-May.Chao@Sun.COM (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
14710500SHai-May.Chao@Sun.COM if (mkstemp(tmpfile_name) == -1) {
14810500SHai-May.Chao@Sun.COM err = errno;
14910500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR,
15010500SHai-May.Chao@Sun.COM gettext("failed to create a temporary file - %s"),
15110500SHai-May.Chao@Sun.COM strerror(err));
15210500SHai-May.Chao@Sun.COM (void) fclose(pfile);
15310500SHai-May.Chao@Sun.COM return (FAILURE);
15410500SHai-May.Chao@Sun.COM }
15510500SHai-May.Chao@Sun.COM
15610500SHai-May.Chao@Sun.COM if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
15710500SHai-May.Chao@Sun.COM err = errno;
15810500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
15910500SHai-May.Chao@Sun.COM tmpfile_name, strerror(err));
16010500SHai-May.Chao@Sun.COM (void) fclose(pfile);
16110500SHai-May.Chao@Sun.COM return (FAILURE);
16210500SHai-May.Chao@Sun.COM }
16310500SHai-May.Chao@Sun.COM
16410500SHai-May.Chao@Sun.COM
16510500SHai-May.Chao@Sun.COM /*
16610500SHai-May.Chao@Sun.COM * Loop thru the config file. If the provider was reserved within a
16710500SHai-May.Chao@Sun.COM * package bracket, just uncomment it. Otherwise, append it at
16810500SHai-May.Chao@Sun.COM * the end. The resulting file will be saved in the temp file first.
16910500SHai-May.Chao@Sun.COM */
17010500SHai-May.Chao@Sun.COM found_count = 0;
17110500SHai-May.Chao@Sun.COM rc = SUCCESS;
17210500SHai-May.Chao@Sun.COM
17310500SHai-May.Chao@Sun.COM while (fgets(buffer, BUFSIZ, pfile) != NULL) {
17410500SHai-May.Chao@Sun.COM found = B_FALSE;
17510500SHai-May.Chao@Sun.COM if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) {
17610500SHai-May.Chao@Sun.COM if (buffer[0] == '#') {
17710500SHai-May.Chao@Sun.COM ptr = buffer;
17810500SHai-May.Chao@Sun.COM ptr++;
17910500SHai-May.Chao@Sun.COM if (strcmp(entry, ptr) == 0) {
18010500SHai-May.Chao@Sun.COM found = B_TRUE;
18110500SHai-May.Chao@Sun.COM found_count++;
18210500SHai-May.Chao@Sun.COM }
183*10979SHai-May.Chao@Sun.COM } else {
184*10979SHai-May.Chao@Sun.COM (void) strlcpy(buffer2, buffer, BUFSIZ);
185*10979SHai-May.Chao@Sun.COM ptr = buffer2;
186*10979SHai-May.Chao@Sun.COM if ((name = strtok(ptr, SEP_COLON)) == NULL) {
187*10979SHai-May.Chao@Sun.COM rc = FAILURE;
188*10979SHai-May.Chao@Sun.COM break;
189*10979SHai-May.Chao@Sun.COM } else if (strcmp(FIPS_KEYWORD, name) == 0) {
190*10979SHai-May.Chao@Sun.COM found = B_TRUE;
191*10979SHai-May.Chao@Sun.COM found_count++;
192*10979SHai-May.Chao@Sun.COM fips_entry = B_TRUE;
193*10979SHai-May.Chao@Sun.COM }
19410500SHai-May.Chao@Sun.COM }
19510500SHai-May.Chao@Sun.COM } else { /* _PATH_KCF_CONF */
19610500SHai-May.Chao@Sun.COM if (buffer[0] == '#') {
19710500SHai-May.Chao@Sun.COM (void) strlcpy(buffer2, buffer, BUFSIZ);
19810500SHai-May.Chao@Sun.COM ptr = buffer2;
19910500SHai-May.Chao@Sun.COM ptr++; /* skip # */
20010500SHai-May.Chao@Sun.COM if ((name = strtok(ptr, SEP_COLON)) == NULL) {
20110500SHai-May.Chao@Sun.COM rc = FAILURE;
20210500SHai-May.Chao@Sun.COM break;
20310500SHai-May.Chao@Sun.COM }
20410500SHai-May.Chao@Sun.COM } else {
20510500SHai-May.Chao@Sun.COM (void) strlcpy(buffer2, buffer, BUFSIZ);
20610500SHai-May.Chao@Sun.COM ptr = buffer2;
20710500SHai-May.Chao@Sun.COM if ((name = strtok(ptr, SEP_COLON)) == NULL) {
20810500SHai-May.Chao@Sun.COM rc = FAILURE;
20910500SHai-May.Chao@Sun.COM break;
21010500SHai-May.Chao@Sun.COM }
21110500SHai-May.Chao@Sun.COM }
21210500SHai-May.Chao@Sun.COM }
21310500SHai-May.Chao@Sun.COM
21410500SHai-May.Chao@Sun.COM if (found == B_FALSE) {
21510500SHai-May.Chao@Sun.COM if (fputs(buffer, pfile_tmp) == EOF) {
21610500SHai-May.Chao@Sun.COM rc = FAILURE;
21710500SHai-May.Chao@Sun.COM }
21810500SHai-May.Chao@Sun.COM } else {
21910500SHai-May.Chao@Sun.COM if (found_count == 1) {
22010500SHai-May.Chao@Sun.COM if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) {
221*10979SHai-May.Chao@Sun.COM if (fips_entry == B_TRUE) {
222*10979SHai-May.Chao@Sun.COM if (fputs(entry, pfile_tmp) ==
223*10979SHai-May.Chao@Sun.COM EOF) {
224*10979SHai-May.Chao@Sun.COM rc = FAILURE;
225*10979SHai-May.Chao@Sun.COM }
226*10979SHai-May.Chao@Sun.COM fips_entry = B_FALSE;
227*10979SHai-May.Chao@Sun.COM } else {
228*10979SHai-May.Chao@Sun.COM if (fputs(ptr, pfile_tmp) ==
229*10979SHai-May.Chao@Sun.COM EOF) {
230*10979SHai-May.Chao@Sun.COM rc = FAILURE;
231*10979SHai-May.Chao@Sun.COM }
23210500SHai-May.Chao@Sun.COM }
23310500SHai-May.Chao@Sun.COM } else {
23410500SHai-May.Chao@Sun.COM if (fputs(entry, pfile_tmp) == EOF) {
23510500SHai-May.Chao@Sun.COM rc = FAILURE;
23610500SHai-May.Chao@Sun.COM }
23710500SHai-May.Chao@Sun.COM }
23810500SHai-May.Chao@Sun.COM } else {
23910500SHai-May.Chao@Sun.COM /*
24010500SHai-May.Chao@Sun.COM * Found a second entry with same tag name.
24110500SHai-May.Chao@Sun.COM * Should not happen. The config file
24210500SHai-May.Chao@Sun.COM * is corrupted. Give a warning and skip
24310500SHai-May.Chao@Sun.COM * this entry.
24410500SHai-May.Chao@Sun.COM */
24510500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext(
24610500SHai-May.Chao@Sun.COM "(Warning) Found an additional reserved "
24710500SHai-May.Chao@Sun.COM "entry for %s."), entry);
24810500SHai-May.Chao@Sun.COM }
24910500SHai-May.Chao@Sun.COM }
25010500SHai-May.Chao@Sun.COM
25110500SHai-May.Chao@Sun.COM if (rc == FAILURE) {
25210500SHai-May.Chao@Sun.COM break;
25310500SHai-May.Chao@Sun.COM }
25410500SHai-May.Chao@Sun.COM }
25510500SHai-May.Chao@Sun.COM
25610500SHai-May.Chao@Sun.COM (void) fclose(pfile);
25710500SHai-May.Chao@Sun.COM
25810500SHai-May.Chao@Sun.COM if (rc == FAILURE) {
25910500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext("write error."));
26010500SHai-May.Chao@Sun.COM (void) fclose(pfile_tmp);
26110500SHai-May.Chao@Sun.COM if (unlink(tmpfile_name) != 0) {
26210500SHai-May.Chao@Sun.COM err = errno;
26310500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext(
26410500SHai-May.Chao@Sun.COM "(Warning) failed to remove %s: %s"), tmpfile_name,
26510500SHai-May.Chao@Sun.COM strerror(err));
26610500SHai-May.Chao@Sun.COM }
26710500SHai-May.Chao@Sun.COM return (FAILURE);
26810500SHai-May.Chao@Sun.COM }
26910500SHai-May.Chao@Sun.COM
27010500SHai-May.Chao@Sun.COM if (found_count == 0) {
27110500SHai-May.Chao@Sun.COM /*
27210500SHai-May.Chao@Sun.COM * The entry was not in config file before, append it to the
27310500SHai-May.Chao@Sun.COM * end of the temp file.
27410500SHai-May.Chao@Sun.COM */
27510500SHai-May.Chao@Sun.COM if (fputs(entry, pfile_tmp) == EOF) {
27610500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext(
27710500SHai-May.Chao@Sun.COM "failed to write to %s: %s"), tmpfile_name,
27810500SHai-May.Chao@Sun.COM strerror(errno));
27910500SHai-May.Chao@Sun.COM (void) fclose(pfile_tmp);
28010500SHai-May.Chao@Sun.COM if (unlink(tmpfile_name) != 0) {
28110500SHai-May.Chao@Sun.COM err = errno;
28210500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext(
28310500SHai-May.Chao@Sun.COM "(Warning) failed to remove %s: %s"),
28410500SHai-May.Chao@Sun.COM tmpfile_name, strerror(err));
28510500SHai-May.Chao@Sun.COM }
28610500SHai-May.Chao@Sun.COM return (FAILURE);
28710500SHai-May.Chao@Sun.COM }
28810500SHai-May.Chao@Sun.COM }
28910500SHai-May.Chao@Sun.COM
29010500SHai-May.Chao@Sun.COM if (fclose(pfile_tmp) != 0) {
29110500SHai-May.Chao@Sun.COM err = errno;
29210500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR,
29310500SHai-May.Chao@Sun.COM gettext("failed to close %s: %s"), tmpfile_name,
29410500SHai-May.Chao@Sun.COM strerror(err));
29510500SHai-May.Chao@Sun.COM return (FAILURE);
29610500SHai-May.Chao@Sun.COM }
29710500SHai-May.Chao@Sun.COM
29810500SHai-May.Chao@Sun.COM if (rename(tmpfile_name, conf_file) == -1) {
29910500SHai-May.Chao@Sun.COM err = errno;
30010500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR,
30110500SHai-May.Chao@Sun.COM gettext("failed to update the configuration - %s"),
30210500SHai-May.Chao@Sun.COM strerror(err));
30310500SHai-May.Chao@Sun.COM cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
30410500SHai-May.Chao@Sun.COM conf_file, strerror(err));
30510500SHai-May.Chao@Sun.COM rc = FAILURE;
30610500SHai-May.Chao@Sun.COM } else if (chmod(conf_file,
30710500SHai-May.Chao@Sun.COM S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
30810500SHai-May.Chao@Sun.COM err = errno;
30910500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR,
31010500SHai-May.Chao@Sun.COM gettext("failed to update the configuration - %s"),
31110500SHai-May.Chao@Sun.COM strerror(err));
31210500SHai-May.Chao@Sun.COM cryptodebug("failed to chmod to %s: %s", conf_file,
31310500SHai-May.Chao@Sun.COM strerror(err));
31410500SHai-May.Chao@Sun.COM rc = FAILURE;
31510500SHai-May.Chao@Sun.COM } else {
31610500SHai-May.Chao@Sun.COM rc = SUCCESS;
31710500SHai-May.Chao@Sun.COM }
31810500SHai-May.Chao@Sun.COM
31910500SHai-May.Chao@Sun.COM if (rc == FAILURE) {
32010500SHai-May.Chao@Sun.COM if (unlink(tmpfile_name) != 0) {
32110500SHai-May.Chao@Sun.COM err = errno;
32210500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext(
32310500SHai-May.Chao@Sun.COM "(Warning) failed to remove %s: %s"),
32410500SHai-May.Chao@Sun.COM tmpfile_name, strerror(err));
32510500SHai-May.Chao@Sun.COM }
32610500SHai-May.Chao@Sun.COM }
32710500SHai-May.Chao@Sun.COM
32810500SHai-May.Chao@Sun.COM return (rc);
32910500SHai-May.Chao@Sun.COM
33010500SHai-May.Chao@Sun.COM }
331