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 5*10500SHai-May.Chao@Sun.COM * Common Development and Distribution License (the "License"). 6*10500SHai-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 /* 22*10500SHai-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> 28*10500SHai-May.Chao@Sun.COM #include <libintl.h> 29*10500SHai-May.Chao@Sun.COM #include <stdio.h> 30*10500SHai-May.Chao@Sun.COM #include <sys/stat.h> 310Sstevel@tonic-gate #include "cryptoadm.h" 32*10500SHai-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 * 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 */ 56*10500SHai-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 */ 62*10500SHai-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 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 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 } 107*10500SHai-May.Chao@Sun.COM 108*10500SHai-May.Chao@Sun.COM int 109*10500SHai-May.Chao@Sun.COM update_conf(char *conf_file, char *entry) 110*10500SHai-May.Chao@Sun.COM { 111*10500SHai-May.Chao@Sun.COM 112*10500SHai-May.Chao@Sun.COM boolean_t found; 113*10500SHai-May.Chao@Sun.COM FILE *pfile; 114*10500SHai-May.Chao@Sun.COM FILE *pfile_tmp; 115*10500SHai-May.Chao@Sun.COM char tmpfile_name[MAXPATHLEN]; 116*10500SHai-May.Chao@Sun.COM char *ptr; 117*10500SHai-May.Chao@Sun.COM char *name; 118*10500SHai-May.Chao@Sun.COM char buffer[BUFSIZ]; 119*10500SHai-May.Chao@Sun.COM char buffer2[BUFSIZ]; 120*10500SHai-May.Chao@Sun.COM int found_count; 121*10500SHai-May.Chao@Sun.COM int rc = SUCCESS; 122*10500SHai-May.Chao@Sun.COM int err; 123*10500SHai-May.Chao@Sun.COM 124*10500SHai-May.Chao@Sun.COM if ((pfile = fopen(conf_file, "r+")) == NULL) { 125*10500SHai-May.Chao@Sun.COM err = errno; 126*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, 127*10500SHai-May.Chao@Sun.COM gettext("failed to update the configuration - %s"), 128*10500SHai-May.Chao@Sun.COM strerror(err)); 129*10500SHai-May.Chao@Sun.COM cryptodebug("failed to open %s for write.", conf_file); 130*10500SHai-May.Chao@Sun.COM return (FAILURE); 131*10500SHai-May.Chao@Sun.COM } 132*10500SHai-May.Chao@Sun.COM 133*10500SHai-May.Chao@Sun.COM if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 134*10500SHai-May.Chao@Sun.COM err = errno; 135*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, 136*10500SHai-May.Chao@Sun.COM gettext("failed to lock the configuration - %s"), 137*10500SHai-May.Chao@Sun.COM strerror(err)); 138*10500SHai-May.Chao@Sun.COM (void) fclose(pfile); 139*10500SHai-May.Chao@Sun.COM return (FAILURE); 140*10500SHai-May.Chao@Sun.COM } 141*10500SHai-May.Chao@Sun.COM 142*10500SHai-May.Chao@Sun.COM /* 143*10500SHai-May.Chao@Sun.COM * Create a temporary file in the /etc/crypto directory. 144*10500SHai-May.Chao@Sun.COM */ 145*10500SHai-May.Chao@Sun.COM (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 146*10500SHai-May.Chao@Sun.COM if (mkstemp(tmpfile_name) == -1) { 147*10500SHai-May.Chao@Sun.COM err = errno; 148*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, 149*10500SHai-May.Chao@Sun.COM gettext("failed to create a temporary file - %s"), 150*10500SHai-May.Chao@Sun.COM strerror(err)); 151*10500SHai-May.Chao@Sun.COM (void) fclose(pfile); 152*10500SHai-May.Chao@Sun.COM return (FAILURE); 153*10500SHai-May.Chao@Sun.COM } 154*10500SHai-May.Chao@Sun.COM 155*10500SHai-May.Chao@Sun.COM if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 156*10500SHai-May.Chao@Sun.COM err = errno; 157*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 158*10500SHai-May.Chao@Sun.COM tmpfile_name, strerror(err)); 159*10500SHai-May.Chao@Sun.COM (void) fclose(pfile); 160*10500SHai-May.Chao@Sun.COM return (FAILURE); 161*10500SHai-May.Chao@Sun.COM } 162*10500SHai-May.Chao@Sun.COM 163*10500SHai-May.Chao@Sun.COM 164*10500SHai-May.Chao@Sun.COM /* 165*10500SHai-May.Chao@Sun.COM * Loop thru the config file. If the provider was reserved within a 166*10500SHai-May.Chao@Sun.COM * package bracket, just uncomment it. Otherwise, append it at 167*10500SHai-May.Chao@Sun.COM * the end. The resulting file will be saved in the temp file first. 168*10500SHai-May.Chao@Sun.COM */ 169*10500SHai-May.Chao@Sun.COM found_count = 0; 170*10500SHai-May.Chao@Sun.COM rc = SUCCESS; 171*10500SHai-May.Chao@Sun.COM 172*10500SHai-May.Chao@Sun.COM while (fgets(buffer, BUFSIZ, pfile) != NULL) { 173*10500SHai-May.Chao@Sun.COM found = B_FALSE; 174*10500SHai-May.Chao@Sun.COM if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) { 175*10500SHai-May.Chao@Sun.COM if (buffer[0] == '#') { 176*10500SHai-May.Chao@Sun.COM ptr = buffer; 177*10500SHai-May.Chao@Sun.COM ptr++; 178*10500SHai-May.Chao@Sun.COM if (strcmp(entry, ptr) == 0) { 179*10500SHai-May.Chao@Sun.COM found = B_TRUE; 180*10500SHai-May.Chao@Sun.COM found_count++; 181*10500SHai-May.Chao@Sun.COM } 182*10500SHai-May.Chao@Sun.COM } 183*10500SHai-May.Chao@Sun.COM } else { /* _PATH_KCF_CONF */ 184*10500SHai-May.Chao@Sun.COM if (buffer[0] == '#') { 185*10500SHai-May.Chao@Sun.COM (void) strlcpy(buffer2, buffer, BUFSIZ); 186*10500SHai-May.Chao@Sun.COM ptr = buffer2; 187*10500SHai-May.Chao@Sun.COM ptr++; /* skip # */ 188*10500SHai-May.Chao@Sun.COM if ((name = strtok(ptr, SEP_COLON)) == NULL) { 189*10500SHai-May.Chao@Sun.COM rc = FAILURE; 190*10500SHai-May.Chao@Sun.COM break; 191*10500SHai-May.Chao@Sun.COM } else if (strcmp(FIPS_KEYWORD, name) == 0) { 192*10500SHai-May.Chao@Sun.COM found = B_TRUE; 193*10500SHai-May.Chao@Sun.COM found_count++; 194*10500SHai-May.Chao@Sun.COM } 195*10500SHai-May.Chao@Sun.COM } else { 196*10500SHai-May.Chao@Sun.COM (void) strlcpy(buffer2, buffer, BUFSIZ); 197*10500SHai-May.Chao@Sun.COM ptr = buffer2; 198*10500SHai-May.Chao@Sun.COM if ((name = strtok(ptr, SEP_COLON)) == NULL) { 199*10500SHai-May.Chao@Sun.COM rc = FAILURE; 200*10500SHai-May.Chao@Sun.COM break; 201*10500SHai-May.Chao@Sun.COM } else if (strcmp(FIPS_KEYWORD, name) == 0) { 202*10500SHai-May.Chao@Sun.COM found = B_TRUE; 203*10500SHai-May.Chao@Sun.COM found_count++; 204*10500SHai-May.Chao@Sun.COM } 205*10500SHai-May.Chao@Sun.COM } 206*10500SHai-May.Chao@Sun.COM } 207*10500SHai-May.Chao@Sun.COM 208*10500SHai-May.Chao@Sun.COM if (found == B_FALSE) { 209*10500SHai-May.Chao@Sun.COM if (fputs(buffer, pfile_tmp) == EOF) { 210*10500SHai-May.Chao@Sun.COM rc = FAILURE; 211*10500SHai-May.Chao@Sun.COM } 212*10500SHai-May.Chao@Sun.COM } else { 213*10500SHai-May.Chao@Sun.COM if (found_count == 1) { 214*10500SHai-May.Chao@Sun.COM if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) { 215*10500SHai-May.Chao@Sun.COM if (fputs(ptr, pfile_tmp) == EOF) { 216*10500SHai-May.Chao@Sun.COM rc = FAILURE; 217*10500SHai-May.Chao@Sun.COM } 218*10500SHai-May.Chao@Sun.COM } else { 219*10500SHai-May.Chao@Sun.COM if (fputs(entry, pfile_tmp) == EOF) { 220*10500SHai-May.Chao@Sun.COM rc = FAILURE; 221*10500SHai-May.Chao@Sun.COM } 222*10500SHai-May.Chao@Sun.COM } 223*10500SHai-May.Chao@Sun.COM } else { 224*10500SHai-May.Chao@Sun.COM /* 225*10500SHai-May.Chao@Sun.COM * Found a second entry with same tag name. 226*10500SHai-May.Chao@Sun.COM * Should not happen. The config file 227*10500SHai-May.Chao@Sun.COM * is corrupted. Give a warning and skip 228*10500SHai-May.Chao@Sun.COM * this entry. 229*10500SHai-May.Chao@Sun.COM */ 230*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext( 231*10500SHai-May.Chao@Sun.COM "(Warning) Found an additional reserved " 232*10500SHai-May.Chao@Sun.COM "entry for %s."), entry); 233*10500SHai-May.Chao@Sun.COM } 234*10500SHai-May.Chao@Sun.COM } 235*10500SHai-May.Chao@Sun.COM 236*10500SHai-May.Chao@Sun.COM if (rc == FAILURE) { 237*10500SHai-May.Chao@Sun.COM break; 238*10500SHai-May.Chao@Sun.COM } 239*10500SHai-May.Chao@Sun.COM } 240*10500SHai-May.Chao@Sun.COM 241*10500SHai-May.Chao@Sun.COM (void) fclose(pfile); 242*10500SHai-May.Chao@Sun.COM 243*10500SHai-May.Chao@Sun.COM if (rc == FAILURE) { 244*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext("write error.")); 245*10500SHai-May.Chao@Sun.COM (void) fclose(pfile_tmp); 246*10500SHai-May.Chao@Sun.COM if (unlink(tmpfile_name) != 0) { 247*10500SHai-May.Chao@Sun.COM err = errno; 248*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext( 249*10500SHai-May.Chao@Sun.COM "(Warning) failed to remove %s: %s"), tmpfile_name, 250*10500SHai-May.Chao@Sun.COM strerror(err)); 251*10500SHai-May.Chao@Sun.COM } 252*10500SHai-May.Chao@Sun.COM return (FAILURE); 253*10500SHai-May.Chao@Sun.COM } 254*10500SHai-May.Chao@Sun.COM 255*10500SHai-May.Chao@Sun.COM if (found_count == 0) { 256*10500SHai-May.Chao@Sun.COM /* 257*10500SHai-May.Chao@Sun.COM * The entry was not in config file before, append it to the 258*10500SHai-May.Chao@Sun.COM * end of the temp file. 259*10500SHai-May.Chao@Sun.COM */ 260*10500SHai-May.Chao@Sun.COM if (fputs(entry, pfile_tmp) == EOF) { 261*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext( 262*10500SHai-May.Chao@Sun.COM "failed to write to %s: %s"), tmpfile_name, 263*10500SHai-May.Chao@Sun.COM strerror(errno)); 264*10500SHai-May.Chao@Sun.COM (void) fclose(pfile_tmp); 265*10500SHai-May.Chao@Sun.COM if (unlink(tmpfile_name) != 0) { 266*10500SHai-May.Chao@Sun.COM err = errno; 267*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext( 268*10500SHai-May.Chao@Sun.COM "(Warning) failed to remove %s: %s"), 269*10500SHai-May.Chao@Sun.COM tmpfile_name, strerror(err)); 270*10500SHai-May.Chao@Sun.COM } 271*10500SHai-May.Chao@Sun.COM return (FAILURE); 272*10500SHai-May.Chao@Sun.COM } 273*10500SHai-May.Chao@Sun.COM } 274*10500SHai-May.Chao@Sun.COM 275*10500SHai-May.Chao@Sun.COM if (fclose(pfile_tmp) != 0) { 276*10500SHai-May.Chao@Sun.COM err = errno; 277*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, 278*10500SHai-May.Chao@Sun.COM gettext("failed to close %s: %s"), tmpfile_name, 279*10500SHai-May.Chao@Sun.COM strerror(err)); 280*10500SHai-May.Chao@Sun.COM return (FAILURE); 281*10500SHai-May.Chao@Sun.COM } 282*10500SHai-May.Chao@Sun.COM 283*10500SHai-May.Chao@Sun.COM if (rename(tmpfile_name, conf_file) == -1) { 284*10500SHai-May.Chao@Sun.COM err = errno; 285*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, 286*10500SHai-May.Chao@Sun.COM gettext("failed to update the configuration - %s"), 287*10500SHai-May.Chao@Sun.COM strerror(err)); 288*10500SHai-May.Chao@Sun.COM cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 289*10500SHai-May.Chao@Sun.COM conf_file, strerror(err)); 290*10500SHai-May.Chao@Sun.COM rc = FAILURE; 291*10500SHai-May.Chao@Sun.COM } else if (chmod(conf_file, 292*10500SHai-May.Chao@Sun.COM S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 293*10500SHai-May.Chao@Sun.COM err = errno; 294*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, 295*10500SHai-May.Chao@Sun.COM gettext("failed to update the configuration - %s"), 296*10500SHai-May.Chao@Sun.COM strerror(err)); 297*10500SHai-May.Chao@Sun.COM cryptodebug("failed to chmod to %s: %s", conf_file, 298*10500SHai-May.Chao@Sun.COM strerror(err)); 299*10500SHai-May.Chao@Sun.COM rc = FAILURE; 300*10500SHai-May.Chao@Sun.COM } else { 301*10500SHai-May.Chao@Sun.COM rc = SUCCESS; 302*10500SHai-May.Chao@Sun.COM } 303*10500SHai-May.Chao@Sun.COM 304*10500SHai-May.Chao@Sun.COM if (rc == FAILURE) { 305*10500SHai-May.Chao@Sun.COM if (unlink(tmpfile_name) != 0) { 306*10500SHai-May.Chao@Sun.COM err = errno; 307*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext( 308*10500SHai-May.Chao@Sun.COM "(Warning) failed to remove %s: %s"), 309*10500SHai-May.Chao@Sun.COM tmpfile_name, strerror(err)); 310*10500SHai-May.Chao@Sun.COM } 311*10500SHai-May.Chao@Sun.COM } 312*10500SHai-May.Chao@Sun.COM 313*10500SHai-May.Chao@Sun.COM return (rc); 314*10500SHai-May.Chao@Sun.COM 315*10500SHai-May.Chao@Sun.COM } 316