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 * 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 */ 56bbbb143bSmcpowers 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 */ 62bbbb143bSmcpowers *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 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 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 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 } 183b5a2d845SHai-May Chao } else { 184b5a2d845SHai-May Chao (void) strlcpy(buffer2, buffer, BUFSIZ); 185b5a2d845SHai-May Chao ptr = buffer2; 186b5a2d845SHai-May Chao if ((name = strtok(ptr, SEP_COLON)) == NULL) { 187b5a2d845SHai-May Chao rc = FAILURE; 188b5a2d845SHai-May Chao break; 189b5a2d845SHai-May Chao } else if (strcmp(FIPS_KEYWORD, name) == 0) { 190b5a2d845SHai-May Chao found = B_TRUE; 191b5a2d845SHai-May Chao found_count++; 192*d616ad8eSHai-May Chao fips_entry = B_TRUE; 193*d616ad8eSHai-May Chao } 194*d616ad8eSHai-May Chao } 195*d616ad8eSHai-May Chao } else { /* _PATH_KCF_CONF */ 196*d616ad8eSHai-May Chao if (buffer[0] == '#') { 197*d616ad8eSHai-May Chao (void) strlcpy(buffer2, buffer, BUFSIZ); 198*d616ad8eSHai-May Chao ptr = buffer2; 199*d616ad8eSHai-May Chao ptr++; /* skip # */ 200*d616ad8eSHai-May Chao if ((name = strtok(ptr, SEP_COLON)) == NULL) { 201*d616ad8eSHai-May Chao rc = FAILURE; 202*d616ad8eSHai-May Chao break; 203*d616ad8eSHai-May Chao } 204*d616ad8eSHai-May Chao } else { 205*d616ad8eSHai-May Chao (void) strlcpy(buffer2, buffer, BUFSIZ); 206*d616ad8eSHai-May Chao ptr = buffer2; 207*d616ad8eSHai-May Chao if ((name = strtok(ptr, SEP_COLON)) == NULL) { 208*d616ad8eSHai-May Chao rc = FAILURE; 209*d616ad8eSHai-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) { 224b5a2d845SHai-May Chao rc = FAILURE; 225b5a2d845SHai-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 } 232*d616ad8eSHai-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