Print this page
6414175 kcf.conf's supportedlist not providing much usefulness
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c
+++ new/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <fcntl.h>
27 27 #include <stdio.h>
28 28 #include <stdlib.h>
29 29 #include <strings.h>
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
30 30 #include <unistd.h>
31 31 #include <locale.h>
32 32 #include <libgen.h>
33 33 #include <sys/types.h>
34 34 #include <sys/stat.h>
35 35 #include <sys/crypto/ioctladmin.h>
36 36 #include <signal.h>
37 37 #include <sys/crypto/elfsign.h>
38 38 #include "cryptoadm.h"
39 39
40 -static int err; /* to store the value of errno in case being overwritten */
41 40 static int check_hardware_provider(char *, char *, int *, int *);
42 41
43 42 /*
44 43 * Display the mechanism list for a kernel software provider.
44 + * This implements part of the "cryptoadm list -m" command.
45 + *
46 + * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
47 + * If NULL, this function obtains it by calling get_kcfconf_info() internally.
45 48 */
46 49 int
47 -list_mechlist_for_soft(char *provname)
50 +list_mechlist_for_soft(char *provname,
51 + entrylist_t *phardlist, entrylist_t *psoftlist)
48 52 {
49 - mechlist_t *pmechlist;
50 - int rc;
53 + mechlist_t *pmechlist = NULL;
54 + int rc;
51 55
52 56 if (provname == NULL) {
53 57 return (FAILURE);
54 58 }
55 59
56 - rc = get_soft_info(provname, &pmechlist);
60 + rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
57 61 if (rc == SUCCESS) {
58 62 (void) filter_mechlist(&pmechlist, RANDOM);
59 63 print_mechlist(provname, pmechlist);
60 64 free_mechlist(pmechlist);
61 65 } else {
62 66 cryptoerror(LOG_STDERR, gettext(
63 67 "failed to retrieve the mechanism list for %s."),
64 68 provname);
65 69 }
66 70
67 71 return (rc);
68 -
69 72 }
70 73
71 74 /*
72 75 * Display the mechanism list for a kernel hardware provider.
76 + * This implements part of the "cryptoadm list -m" command.
73 77 */
74 78 int
75 79 list_mechlist_for_hard(char *provname)
76 80 {
77 - mechlist_t *pmechlist;
78 - char devname[MAXNAMELEN];
79 - int inst_num;
80 - int count;
81 - int rc = SUCCESS;
81 + mechlist_t *pmechlist = NULL;
82 + char devname[MAXNAMELEN];
83 + int inst_num;
84 + int count;
85 + int rc = SUCCESS;
82 86
83 87 if (provname == NULL) {
84 88 return (FAILURE);
85 89 }
86 90
87 91 /*
88 92 * Check if the provider is valid. If it is valid, get the number of
89 93 * mechanisms also.
90 94 */
91 95 if (check_hardware_provider(provname, devname, &inst_num, &count) ==
92 96 FAILURE) {
93 97 return (FAILURE);
94 98 }
95 99
96 100 /* Get the mechanism list for the kernel hardware provider */
97 101 if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
98 102 SUCCESS) {
99 103 (void) filter_mechlist(&pmechlist, RANDOM);
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
100 104 print_mechlist(provname, pmechlist);
101 105 free_mechlist(pmechlist);
102 106 }
103 107
104 108 return (rc);
105 109 }
106 110
107 111
108 112 /*
109 113 * Display the policy information for a kernel software provider.
114 + * This implements part of the "cryptoadm list -p" command.
115 + *
116 + * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
117 + * If NULL, this function obtains it by calling get_kcfconf_info() internally.
110 118 */
111 119 int
112 -list_policy_for_soft(char *provname)
120 +list_policy_for_soft(char *provname,
121 + entrylist_t *phardlist, entrylist_t *psoftlist)
113 122 {
114 - int rc;
115 - entry_t *pent = NULL;
116 - mechlist_t *pmechlist;
117 - boolean_t has_random = B_FALSE;
118 - boolean_t has_mechs = B_FALSE;
123 + int rc;
124 + entry_t *pent = NULL;
125 + mechlist_t *pmechlist = NULL;
126 + boolean_t has_random = B_FALSE;
127 + boolean_t has_mechs = B_FALSE;
128 + boolean_t in_kernel = B_FALSE;
119 129
120 130 if (provname == NULL) {
121 131 return (FAILURE);
122 132 }
123 133
124 - if ((pent = getent_kef(provname)) == NULL) {
134 + if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
135 + return (FAILURE);
136 + } else if (in_kernel == B_FALSE) {
125 137 cryptoerror(LOG_STDERR, gettext("%s does not exist."),
126 138 provname);
127 139 return (FAILURE);
128 140 }
141 + pent = getent_kef(provname, phardlist, psoftlist);
129 142
130 - rc = get_soft_info(provname, &pmechlist);
143 + rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
131 144 if (rc == SUCCESS) {
132 145 has_random = filter_mechlist(&pmechlist, RANDOM);
133 146 if (pmechlist != NULL) {
134 147 has_mechs = B_TRUE;
135 148 free_mechlist(pmechlist);
136 149 }
137 150 } else {
138 151 cryptoerror(LOG_STDERR, gettext(
139 152 "failed to retrieve the mechanism list for %s."),
140 153 provname);
141 154 return (rc);
142 155 }
143 156
144 - print_kef_policy(pent, has_random, has_mechs);
157 + print_kef_policy(provname, pent, has_random, has_mechs);
145 158 free_entry(pent);
146 159 return (SUCCESS);
147 160 }
148 161
149 162
150 163
151 164 /*
152 165 * Display the policy information for a kernel hardware provider.
166 + * This implements part of the "cryptoadm list -p" command.
167 + *
168 + * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
169 + * If NULL, this function obtains it by calling get_kcfconf_info() internally.
170 + * Parameter pdevlist is supplied by get_dev_list().
171 + * If NULL, this function obtains it by calling get_dev_list() internally.
153 172 */
154 173 int
155 -list_policy_for_hard(char *provname)
174 +list_policy_for_hard(char *provname,
175 + entrylist_t *phardlist, entrylist_t *psoftlist,
176 + crypto_get_dev_list_t *pdevlist)
156 177 {
157 - entry_t *pent;
158 - boolean_t is_active;
159 - mechlist_t *pmechlist;
160 - char devname[MAXNAMELEN];
161 - int inst_num;
162 - int count;
163 - int rc = SUCCESS;
164 - boolean_t has_random = B_FALSE;
165 - boolean_t has_mechs = B_FALSE;
178 + entry_t *pent = NULL;
179 + boolean_t in_kernel;
180 + mechlist_t *pmechlist = NULL;
181 + char devname[MAXNAMELEN];
182 + int inst_num;
183 + int count;
184 + int rc = SUCCESS;
185 + boolean_t has_random = B_FALSE;
186 + boolean_t has_mechs = B_FALSE;
166 187
167 188 if (provname == NULL) {
168 189 return (FAILURE);
169 190 }
170 191
171 192 /*
172 193 * Check if the provider is valid. If it is valid, get the number of
173 194 * mechanisms also.
174 195 */
175 196 if (check_hardware_provider(provname, devname, &inst_num, &count) ==
176 197 FAILURE) {
177 198 return (FAILURE);
178 199 }
179 200
180 201 /* Get the mechanism list for the kernel hardware provider */
181 202 if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) ==
182 203 SUCCESS) {
183 204 has_random = filter_mechlist(&pmechlist, RANDOM);
184 205
185 206 if (pmechlist != NULL) {
186 207 has_mechs = B_TRUE;
187 208 free_mechlist(pmechlist);
188 209 }
189 210 } else {
190 211 cryptoerror(LOG_STDERR, gettext(
191 212 "failed to retrieve the mechanism list for %s."),
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
192 213 devname);
193 214 return (rc);
194 215 }
195 216
196 217 /*
197 218 * If the hardware provider has an entry in the kcf.conf file,
198 219 * some of its mechanisms must have been disabled. Print out
199 220 * the disabled list from the config file entry. Otherwise,
200 221 * if it is active, then all the mechanisms for it are enabled.
201 222 */
202 - if ((pent = getent_kef(provname)) != NULL) {
203 - print_kef_policy(pent, has_random, has_mechs);
223 + if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) {
224 + print_kef_policy(provname, pent, has_random, has_mechs);
204 225 free_entry(pent);
205 226 return (SUCCESS);
206 227 } else {
207 - if (check_active_for_hard(provname, &is_active) ==
208 - FAILURE) {
228 + if (check_kernel_for_hard(provname, pdevlist,
229 + &in_kernel) == FAILURE) {
209 230 return (FAILURE);
210 - } else if (is_active == B_TRUE) {
231 + } else if (in_kernel == B_TRUE) {
211 232 (void) printf(gettext(
212 233 "%s: all mechanisms are enabled."), provname);
213 234 if (has_random)
214 235 /*
215 236 * TRANSLATION_NOTE
216 237 * "random" is a keyword and not to be
217 238 * translated.
218 239 */
219 240 (void) printf(gettext(" %s is enabled.\n"),
220 241 "random");
221 242 else
222 243 (void) printf("\n");
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
223 244 return (SUCCESS);
224 245 } else {
225 246 cryptoerror(LOG_STDERR,
226 247 gettext("%s does not exist."), provname);
227 248 return (FAILURE);
228 249 }
229 250 }
230 251 }
231 252
232 253
233 -
254 +/*
255 + * Disable a kernel hardware provider.
256 + * This implements the "cryptoadm disable" command for
257 + * kernel hardware providers.
258 + */
234 259 int
235 260 disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
236 261 mechlist_t *dislist)
237 262 {
238 - crypto_load_dev_disabled_t *pload_dev_dis;
239 - mechlist_t *infolist;
240 - entry_t *pent;
241 - boolean_t new_dev_entry = B_FALSE;
242 - char devname[MAXNAMELEN];
243 - int inst_num;
244 - int count;
245 - int fd;
246 - int rc = SUCCESS;
263 + crypto_load_dev_disabled_t *pload_dev_dis = NULL;
264 + mechlist_t *infolist = NULL;
265 + entry_t *pent = NULL;
266 + boolean_t new_dev_entry = B_FALSE;
267 + char devname[MAXNAMELEN];
268 + int inst_num;
269 + int count;
270 + int fd = -1;
271 + int rc = SUCCESS;
247 272
248 273 if (provname == NULL) {
249 274 return (FAILURE);
250 275 }
251 276
252 277 /*
253 278 * Check if the provider is valid. If it is valid, get the number of
254 279 * mechanisms also.
255 280 */
256 281 if (check_hardware_provider(provname, devname, &inst_num, &count)
257 282 == FAILURE) {
258 283 return (FAILURE);
259 284 }
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
260 285
261 286 /* Get the mechanism list for the kernel hardware provider */
262 287 if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) {
263 288 return (FAILURE);
264 289 }
265 290
266 291 /*
267 292 * Get the entry of this hardware provider from the config file.
268 293 * If there is no entry yet, create one for it.
269 294 */
270 - if ((pent = getent_kef(provname)) == NULL) {
271 - if ((pent = malloc(sizeof (entry_t))) == NULL) {
295 + if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
296 + if ((pent = create_entry(provname)) == NULL) {
272 297 cryptoerror(LOG_STDERR, gettext("out of memory."));
273 298 free_mechlist(infolist);
274 299 return (FAILURE);
275 300 }
276 301 new_dev_entry = B_TRUE;
277 - (void) strlcpy(pent->name, provname, MAXNAMELEN);
278 - pent->suplist = NULL;
279 - pent->sup_count = 0;
280 - pent->dislist = NULL;
281 - pent->dis_count = 0;
282 302 }
283 303
284 304 /*
285 305 * kCF treats random as an internal mechanism. So, we need to
286 306 * filter it from the mechanism list here, if we are NOT disabling
287 307 * or enabling the random feature. Note that we map random feature at
288 308 * cryptoadm(1M) level to the "random" mechanism in kCF.
289 309 */
290 310 if (!rndflag) {
291 311 (void) filter_mechlist(&dislist, RANDOM);
292 312 }
293 313
294 314 /* Calculate the new disabled list */
295 315 if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
296 316 free_mechlist(infolist);
297 317 free_entry(pent);
298 318 return (FAILURE);
299 319 }
300 320 free_mechlist(infolist);
301 321
302 322 /* If no mechanisms are to be disabled, return */
303 323 if (pent->dis_count == 0) {
304 324 free_entry(pent);
305 325 return (SUCCESS);
306 326 }
307 327
308 328 /* Update the config file with the new entry or the updated entry */
309 329 if (new_dev_entry) {
310 330 rc = update_kcfconf(pent, ADD_MODE);
311 331 } else {
312 332 rc = update_kcfconf(pent, MODIFY_MODE);
313 333 }
314 334
315 335 if (rc == FAILURE) {
316 336 free_entry(pent);
317 337 return (FAILURE);
318 338 }
319 339
320 340 /* Inform kernel about the new disabled mechanism list */
321 341 if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
322 342 free_entry(pent);
323 343 return (FAILURE);
324 344 }
325 345 free_entry(pent);
326 346
327 347 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
328 348 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
329 349 ADMIN_IOCTL_DEVICE, strerror(errno));
330 350 free(pload_dev_dis);
331 351 return (FAILURE);
332 352 }
333 353
334 354 if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
335 355 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s",
336 356 strerror(errno));
337 357 free(pload_dev_dis);
338 358 (void) close(fd);
339 359 return (FAILURE);
340 360 }
341 361
342 362 if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
343 363 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = "
344 364 "%d", pload_dev_dis->dd_return_value);
345 365 free(pload_dev_dis);
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
346 366 (void) close(fd);
347 367 return (FAILURE);
348 368 }
349 369
350 370 free(pload_dev_dis);
351 371 (void) close(fd);
352 372 return (SUCCESS);
353 373 }
354 374
355 375
356 -
376 +/*
377 + * Disable a kernel software provider.
378 + * This implements the "cryptoadm disable" command for
379 + * kernel software providers.
380 + */
357 381 int
358 382 disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
359 383 mechlist_t *dislist)
360 384 {
361 385 crypto_load_soft_disabled_t *pload_soft_dis = NULL;
362 - mechlist_t *infolist;
363 - entry_t *pent;
364 - boolean_t is_active;
365 - int fd;
386 + mechlist_t *infolist = NULL;
387 + entry_t *pent = NULL;
388 + entrylist_t *phardlist = NULL;
389 + entrylist_t *psoftlist = NULL;
390 + boolean_t in_kernel = B_FALSE;
391 + int fd = -1;
392 + int rc = SUCCESS;
366 393
367 394 if (provname == NULL) {
368 395 return (FAILURE);
369 396 }
370 397
371 - /* Get the entry of this provider from the config file. */
372 - if ((pent = getent_kef(provname)) == NULL) {
373 - cryptoerror(LOG_STDERR,
374 - gettext("%s does not exist."), provname);
375 - return (FAILURE);
376 - }
377 -
378 398 /*
379 399 * Check if the kernel software provider is currently unloaded.
380 400 * If it is unloaded, return FAILURE, because the disable subcommand
381 401 * can not perform on inactive (unloaded) providers.
382 402 */
383 - if (check_active_for_soft(provname, &is_active) == FAILURE) {
384 - free_entry(pent);
403 + if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
385 404 return (FAILURE);
386 - } else if (is_active == B_FALSE) {
387 - /*
388 - * TRANSLATION_NOTE
389 - * "disable" is a keyword and not to be translated.
390 - */
405 + } else if (in_kernel == B_FALSE) {
391 406 cryptoerror(LOG_STDERR,
392 - gettext("can not do %1$s on an unloaded "
393 - "kernel software provider -- %2$s."), "disable", provname);
394 - free_entry(pent);
407 + gettext("%s is not loaded or does not exist."),
408 + provname);
395 409 return (FAILURE);
396 410 }
397 411
398 - /* Get the mechanism list for the software provider */
399 - if (get_soft_info(provname, &infolist) == FAILURE) {
400 - free(pent);
412 + if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) {
413 + cryptoerror(LOG_ERR,
414 + "failed to retrieve the providers' "
415 + "information from the configuration file - %s.",
416 + _PATH_KCF_CONF);
401 417 return (FAILURE);
402 418 }
403 419
404 - /* See comments in disable_kef_hardware() */
420 + /*
421 + * Get the entry of this provider from the kcf.conf file, if any.
422 + * Otherwise, create a new kcf.conf entry for writing back to the file.
423 + */
424 + pent = getent_kef(provname, phardlist, psoftlist);
425 + if (pent == NULL) { /* create a new entry */
426 + pent = create_entry(provname);
427 + if (pent == NULL) {
428 + cryptodebug("out of memory.");
429 + rc = FAILURE;
430 + goto out;
431 + }
432 + }
433 +
434 + /* Get the mechanism list for the software provider from the kernel */
435 + if (get_soft_info(provname, &infolist, phardlist, psoftlist) ==
436 + FAILURE) {
437 + rc = FAILURE;
438 + goto out;
439 + }
440 +
441 + if ((infolist != NULL) && (infolist->name[0] != '\0')) {
442 + /*
443 + * Replace the supportedlist from kcf.conf with possibly
444 + * more-up-to-date list from the kernel. This is the case
445 + * for default software providers that had more mechanisms
446 + * added in the current version of the kernel.
447 + */
448 + free_mechlist(pent->suplist);
449 + pent->suplist = infolist;
450 + }
451 +
452 + /*
453 + * kCF treats random as an internal mechanism. So, we need to
454 + * filter it from the mechanism list here, if we are NOT disabling
455 + * or enabling the random feature. Note that we map random feature at
456 + * cryptoadm(1M) level to the "random" mechanism in kCF.
457 + */
405 458 if (!rndflag) {
406 459 (void) filter_mechlist(&infolist, RANDOM);
407 460 }
408 461
409 462 /* Calculate the new disabled list */
410 463 if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
411 - free_entry(pent);
412 - free_mechlist(infolist);
413 - return (FAILURE);
464 + rc = FAILURE;
465 + goto out;
414 466 }
415 467
416 - /* infolist is no longer needed; free it */
417 - free_mechlist(infolist);
418 -
419 468 /* Update the kcf.conf file with the updated entry */
420 469 if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) {
421 - free_entry(pent);
422 - return (FAILURE);
470 + rc = FAILURE;
471 + goto out;
423 472 }
424 473
425 - /* Inform kernel about the new disabled list. */
474 + /* Setup argument to inform kernel about the new disabled list. */
426 475 if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
427 - free_entry(pent);
428 - return (FAILURE);
476 + rc = FAILURE;
477 + goto out;
429 478 }
430 479
431 - /* pent is no longer needed; free it. */
432 - free_entry(pent);
433 -
434 480 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
435 481 cryptoerror(LOG_STDERR,
436 482 gettext("failed to open %s for RW: %s"),
437 483 ADMIN_IOCTL_DEVICE, strerror(errno));
438 - free(pload_soft_dis);
439 - return (FAILURE);
484 + rc = FAILURE;
485 + goto out;
440 486 }
441 487
488 + /* Inform kernel about the new disabled list. */
442 489 if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
443 490 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
444 491 strerror(errno));
445 - free(pload_soft_dis);
446 - (void) close(fd);
447 - return (FAILURE);
492 + rc = FAILURE;
493 + goto out;
448 494 }
449 495
450 496 if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
451 497 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
452 498 "%d", pload_soft_dis->sd_return_value);
453 - free(pload_soft_dis);
454 - (void) close(fd);
455 - return (FAILURE);
499 + rc = FAILURE;
500 + goto out;
456 501 }
457 502
503 +out:
504 + free_entrylist(phardlist);
505 + free_entrylist(psoftlist);
506 + free_mechlist(infolist);
507 + free_entry(pent);
458 508 free(pload_soft_dis);
459 - (void) close(fd);
460 - return (SUCCESS);
509 + if (fd != -1)
510 + (void) close(fd);
511 + return (rc);
461 512 }
462 513
463 514
515 +/*
516 + * Enable a kernel software or hardware provider.
517 + * This implements the "cryptoadm enable" command for kernel providers.
518 + */
464 519 int
465 520 enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
466 521 mechlist_t *mlist)
467 522 {
468 523 crypto_load_soft_disabled_t *pload_soft_dis = NULL;
469 524 crypto_load_dev_disabled_t *pload_dev_dis = NULL;
470 - entry_t *pent;
471 - boolean_t redo_flag = B_FALSE;
472 - int fd;
473 - int rc = SUCCESS;
525 + entry_t *pent = NULL;
526 + boolean_t redo_flag = B_FALSE;
527 + boolean_t in_kernel = B_FALSE;
528 + int fd = -1;
529 + int rc = SUCCESS;
474 530
475 531
476 - /* Get the entry with the provider name from the kcf.conf file */
477 - pent = getent_kef(provname);
532 + /* Get the entry of this provider from the kcf.conf file, if any. */
533 + pent = getent_kef(provname, NULL, NULL);
478 534
479 535 if (is_device(provname)) {
480 536 if (pent == NULL) {
481 537 /*
482 538 * This device doesn't have an entry in the config
483 539 * file, therefore nothing is disabled.
484 540 */
485 541 cryptoerror(LOG_STDERR, gettext(
486 542 "all mechanisms are enabled already for %s."),
487 543 provname);
544 + free_entry(pent);
488 545 return (SUCCESS);
489 546 }
490 547 } else { /* a software module */
491 - if (pent == NULL) {
492 - cryptoerror(LOG_STDERR,
493 - gettext("%s does not exist."), provname);
548 + if (check_kernel_for_soft(provname, NULL, &in_kernel) ==
549 + FAILURE) {
550 + free_entry(pent);
494 551 return (FAILURE);
495 - } else if (pent->dis_count == 0) {
552 + } else if (in_kernel == B_FALSE) {
553 + cryptoerror(LOG_STDERR, gettext("%s does not exist."),
554 + provname);
555 + free_entry(pent);
556 + return (FAILURE);
557 + } else if ((pent == NULL) || (pent->dis_count == 0)) {
496 558 /* nothing to be enabled. */
497 559 cryptoerror(LOG_STDERR, gettext(
498 560 "all mechanisms are enabled already for %s."),
499 561 provname);
500 562 free_entry(pent);
501 563 return (SUCCESS);
502 564 }
503 565 }
504 566
567 + /*
568 + * kCF treats random as an internal mechanism. So, we need to
569 + * filter it from the mechanism list here, if we are NOT disabling
570 + * or enabling the random feature. Note that we map random feature at
571 + * cryptoadm(1M) level to the "random" mechanism in kCF.
572 + */
505 573 if (!rndflag) {
506 - /* See comments in disable_kef_hardware() */
507 574 redo_flag = filter_mechlist(&pent->dislist, RANDOM);
508 575 if (redo_flag)
509 576 pent->dis_count--;
510 577 }
511 578
512 579 /* Update the entry by enabling mechanisms for this provider */
513 580 if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) {
514 581 free_entry(pent);
515 582 return (rc);
516 583 }
517 584
518 585 if (redo_flag) {
519 586 mechlist_t *tmp;
520 587
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
521 588 if ((tmp = create_mech(RANDOM)) == NULL) {
522 589 free_entry(pent);
523 590 return (FAILURE);
524 591 }
525 592 tmp->next = pent->dislist;
526 593 pent->dislist = tmp;
527 594 pent->dis_count++;
528 595 }
529 596
530 597 /*
531 - * Update the kcf.conf file with the updated entry.
598 + * Update the kcf.conf file with the updated entry.
532 599 * For a hardware provider, if there is no more disabled mechanism,
533 - * the entire entry in the config file should be removed.
600 + * remove the entire kcf.conf entry.
534 601 */
535 602 if (is_device(pent->name) && (pent->dis_count == 0)) {
536 603 rc = update_kcfconf(pent, DELETE_MODE);
537 604 } else {
538 605 rc = update_kcfconf(pent, MODIFY_MODE);
539 606 }
540 607
541 608 if (rc == FAILURE) {
542 609 free_entry(pent);
543 610 return (FAILURE);
544 611 }
545 612
546 613
547 614 /* Inform Kernel about the policy change */
548 615
549 616 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
550 617 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
551 618 ADMIN_IOCTL_DEVICE, strerror(errno));
619 + free_entry(pent);
552 620 return (FAILURE);
553 621 }
554 622
555 623 if (is_device(provname)) {
556 624 /* LOAD_DEV_DISABLED */
557 625 if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
626 + free_entry(pent);
558 627 return (FAILURE);
559 628 }
560 629
561 630 if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
562 631 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
563 632 "%s", strerror(errno));
633 + free_entry(pent);
564 634 free(pload_dev_dis);
565 635 (void) close(fd);
566 636 return (FAILURE);
567 637 }
568 638
569 639 if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
570 640 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
571 641 "return_value = %d",
572 642 pload_dev_dis->dd_return_value);
643 + free_entry(pent);
573 644 free(pload_dev_dis);
574 645 (void) close(fd);
575 646 return (FAILURE);
576 647 }
577 648
578 - } else {
649 + } else { /* a software module */
579 650 /* LOAD_SOFT_DISABLED */
580 651 if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
652 + free_entry(pent);
581 653 return (FAILURE);
582 654 }
583 655
584 656 if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis)
585 657 == -1) {
586 658 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
587 659 "%s", strerror(errno));
660 + free_entry(pent);
588 661 free(pload_soft_dis);
589 662 (void) close(fd);
590 663 return (FAILURE);
591 664 }
592 665
593 666 if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
594 667 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
595 668 "return_value = %d",
596 669 pload_soft_dis->sd_return_value);
670 + free_entry(pent);
597 671 free(pload_soft_dis);
598 672 (void) close(fd);
599 673 return (FAILURE);
600 674 }
601 675 }
602 676
677 + free_entry(pent);
678 + free(pload_soft_dis);
603 679 (void) close(fd);
604 680 return (SUCCESS);
605 681 }
606 682
607 683
608 684 /*
609 685 * Install a software module with the specified mechanism list into the system.
610 686 * This routine adds an entry into the config file for this software module
611 687 * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel
612 688 * about the new addition.
613 689 */
614 690 int
615 691 install_kef(char *provname, mechlist_t *mlist)
616 692 {
617 693 crypto_load_soft_config_t *pload_soft_conf = NULL;
618 - boolean_t found;
619 - entry_t *pent;
620 - FILE *pfile;
621 - FILE *pfile_tmp;
622 - char tmpfile_name[MAXPATHLEN];
623 - char *ptr;
624 - char *str;
625 - char *name;
626 - char buffer[BUFSIZ];
627 - char buffer2[BUFSIZ];
628 - int found_count;
629 - int fd;
630 - int rc = SUCCESS;
694 + boolean_t found;
695 + entry_t *pent = NULL;
696 + FILE *pfile = NULL;
697 + FILE *pfile_tmp = NULL;
698 + char tmpfile_name[MAXPATHLEN];
699 + char *ptr;
700 + char *str;
701 + char *name;
702 + char buffer[BUFSIZ];
703 + char buffer2[BUFSIZ];
704 + int found_count;
705 + int fd = -1;
706 + int rc = SUCCESS;
707 + int err;
631 708
632 709 if ((provname == NULL) || (mlist == NULL)) {
633 710 return (FAILURE);
634 711 }
635 712
636 713 /* Check if the provider already exists */
637 - if ((pent = getent_kef(provname)) != NULL) {
714 + if ((pent = getent_kef(provname, NULL, NULL)) != NULL) {
638 715 cryptoerror(LOG_STDERR, gettext("%s exists already."),
639 716 provname);
640 717 free_entry(pent);
641 718 return (FAILURE);
642 719 }
643 720
644 721 /* Create an entry with provname and mlist. */
645 - if ((pent = malloc(sizeof (entry_t))) == NULL) {
722 + if ((pent = create_entry(provname)) == NULL) {
646 723 cryptoerror(LOG_STDERR, gettext("out of memory."));
647 724 return (FAILURE);
648 725 }
649 -
650 - (void) strlcpy(pent->name, provname, MAXNAMELEN);
651 726 pent->sup_count = get_mech_count(mlist);
652 727 pent->suplist = mlist;
653 - pent->dis_count = 0;
654 - pent->dislist = NULL;
655 728
656 729 /* Append an entry for this software module to the kcf.conf file. */
657 730 if ((str = ent2str(pent)) == NULL) {
658 731 free_entry(pent);
659 732 return (FAILURE);
660 733 }
661 734
662 735 if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
663 736 err = errno;
664 737 cryptoerror(LOG_STDERR,
665 738 gettext("failed to update the configuration - %s"),
666 739 strerror(err));
667 740 cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
668 741 free_entry(pent);
669 742 return (FAILURE);
670 743 }
671 744
672 745 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
673 746 err = errno;
674 747 cryptoerror(LOG_STDERR,
675 748 gettext("failed to lock the configuration - %s"),
676 749 strerror(err));
677 750 free_entry(pent);
678 751 (void) fclose(pfile);
679 752 return (FAILURE);
680 753 }
681 754
682 755 /*
683 756 * Create a temporary file in the /etc/crypto directory.
684 757 */
685 758 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
686 759 if (mkstemp(tmpfile_name) == -1) {
687 760 err = errno;
688 761 cryptoerror(LOG_STDERR,
689 762 gettext("failed to create a temporary file - %s"),
690 763 strerror(err));
691 764 free_entry(pent);
692 765 (void) fclose(pfile);
693 766 return (FAILURE);
694 767 }
695 768
696 769 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
697 770 err = errno;
698 771 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
699 772 tmpfile_name, strerror(err));
700 773 free_entry(pent);
701 774 (void) fclose(pfile);
702 775 return (FAILURE);
703 776 }
704 777
705 778
706 779 /*
707 780 * Loop thru the config file. If the provider was reserved within a
708 781 * package bracket, just uncomment it. Otherwise, append it at
709 782 * the end. The resulting file will be saved in the temp file first.
710 783 */
711 784 found_count = 0;
712 785 rc = SUCCESS;
713 786 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
714 787 found = B_FALSE;
715 788 if (buffer[0] == '#') {
716 789 (void) strlcpy(buffer2, buffer, BUFSIZ);
717 790 ptr = buffer2;
718 791 ptr++;
719 792 if ((name = strtok(ptr, SEP_COLON)) == NULL) {
720 793 rc = FAILURE;
721 794 break;
722 795 } else if (strcmp(provname, name) == 0) {
723 796 found = B_TRUE;
724 797 found_count++;
725 798 }
726 799 }
727 800
728 801 if (found == B_FALSE) {
729 802 if (fputs(buffer, pfile_tmp) == EOF) {
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
730 803 rc = FAILURE;
731 804 }
732 805 } else {
733 806 if (found_count == 1) {
734 807 if (fputs(str, pfile_tmp) == EOF) {
735 808 rc = FAILURE;
736 809 }
737 810 } else {
738 811 /*
739 812 * Found a second entry with #libname.
740 - * Should not happen. The kcf.conf ffile
813 + * Should not happen. The kcf.conf file
741 814 * is corrupted. Give a warning and skip
742 815 * this entry.
743 816 */
744 817 cryptoerror(LOG_STDERR, gettext(
745 818 "(Warning) Found an additional reserved "
746 819 "entry for %s."), provname);
747 820 }
748 821 }
749 822
750 823 if (rc == FAILURE) {
751 824 break;
752 825 }
753 826 }
754 827 (void) fclose(pfile);
755 828
756 829 if (rc == FAILURE) {
757 830 cryptoerror(LOG_STDERR, gettext("write error."));
758 831 (void) fclose(pfile_tmp);
759 832 if (unlink(tmpfile_name) != 0) {
760 833 err = errno;
761 834 cryptoerror(LOG_STDERR, gettext(
762 835 "(Warning) failed to remove %s: %s"), tmpfile_name,
763 836 strerror(err));
764 837 }
765 838 free_entry(pent);
766 839 return (FAILURE);
767 840 }
768 841
769 842 if (found_count == 0) {
770 843 /*
771 844 * This libname was not in package before, append it to the
772 845 * end of the temp file.
773 846 */
774 847 if (fputs(str, pfile_tmp) == EOF) {
775 848 cryptoerror(LOG_STDERR, gettext(
776 849 "failed to write to %s: %s"), tmpfile_name,
777 850 strerror(errno));
778 851 (void) fclose(pfile_tmp);
779 852 if (unlink(tmpfile_name) != 0) {
780 853 err = errno;
781 854 cryptoerror(LOG_STDERR, gettext(
782 855 "(Warning) failed to remove %s: %s"),
783 856 tmpfile_name, strerror(err));
784 857 }
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
785 858 free_entry(pent);
786 859 return (FAILURE);
787 860 }
788 861 }
789 862
790 863 if (fclose(pfile_tmp) != 0) {
791 864 err = errno;
792 865 cryptoerror(LOG_STDERR,
793 866 gettext("failed to close %s: %s"), tmpfile_name,
794 867 strerror(err));
868 + free_entry(pent);
795 869 return (FAILURE);
796 870 }
797 871
798 872 if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
799 873 err = errno;
800 874 cryptoerror(LOG_STDERR,
801 875 gettext("failed to update the configuration - %s"),
802 - strerror(err));
876 + strerror(err));
803 877 cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
804 878 _PATH_KCF_CONF, strerror(err));
805 879 rc = FAILURE;
806 880 } else if (chmod(_PATH_KCF_CONF,
807 881 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
808 882 err = errno;
809 883 cryptoerror(LOG_STDERR,
810 884 gettext("failed to update the configuration - %s"),
811 885 strerror(err));
812 886 cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
813 887 strerror(err));
814 888 rc = FAILURE;
815 889 } else {
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
816 890 rc = SUCCESS;
817 891 }
818 892
819 893 if (rc == FAILURE) {
820 894 if (unlink(tmpfile_name) != 0) {
821 895 err = errno;
822 896 cryptoerror(LOG_STDERR, gettext(
823 897 "(Warning) failed to remove %s: %s"),
824 898 tmpfile_name, strerror(err));
825 899 }
900 + free_entry(pent);
826 901 return (FAILURE);
827 902 }
828 903
829 904
830 905 /* Inform kernel of this new software module. */
831 906
832 907 if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
833 908 free_entry(pent);
834 909 return (FAILURE);
835 910 }
836 911
837 912 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
838 913 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
839 914 ADMIN_IOCTL_DEVICE, strerror(errno));
840 915 free_entry(pent);
841 916 free(pload_soft_conf);
842 917 return (FAILURE);
843 918 }
844 919
845 920 if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
846 921 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
847 922 strerror(errno));
848 923 free_entry(pent);
849 924 free(pload_soft_conf);
850 925 (void) close(fd);
851 926 return (FAILURE);
852 927 }
853 928
854 929 if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
855 930 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, "
856 931 "return_value = %d", pload_soft_conf->sc_return_value);
857 932 free_entry(pent);
858 933 free(pload_soft_conf);
859 934 (void) close(fd);
860 935 return (FAILURE);
861 936 }
862 937
863 938 free_entry(pent);
864 939 free(pload_soft_conf);
865 940 (void) close(fd);
866 941 return (SUCCESS);
867 942 }
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
868 943
869 944 /*
870 945 * Uninstall the software module. This routine first unloads the software
871 946 * module with 3 ioctl calls, then deletes its entry from the config file.
872 947 * Removing an entry from the config file needs to be done last to ensure
873 948 * that there is still an entry if the earlier unload failed for any reason.
874 949 */
875 950 int
876 951 uninstall_kef(char *provname)
877 952 {
878 - entry_t *pent;
879 - boolean_t is_active;
880 - boolean_t in_package;
881 - boolean_t found;
882 - FILE *pfile;
883 - FILE *pfile_tmp;
884 - char tmpfile_name[MAXPATHLEN];
885 - char *name;
886 - char strbuf[BUFSIZ];
887 - char buffer[BUFSIZ];
888 - char buffer2[BUFSIZ];
889 - char *str;
890 - int len;
891 - int rc = SUCCESS;
953 + entry_t *pent = NULL;
954 + int rc = SUCCESS;
955 + boolean_t in_kernel = B_FALSE;
956 + boolean_t in_kcfconf = B_FALSE;
957 + int fd = -1;
958 + crypto_load_soft_config_t *pload_soft_conf = NULL;
892 959
893 -
894 - /* Check if it is in the kcf.conf file first. */
895 - if ((pent = getent_kef(provname)) == NULL) {
896 - cryptoerror(LOG_STDERR,
897 - gettext("%s does not exist."), provname);
960 + /* Check to see if the provider exists first. */
961 + if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
898 962 return (FAILURE);
963 + } else if (in_kernel == B_FALSE) {
964 + cryptoerror(LOG_STDERR, gettext("%s does not exist."),
965 + provname);
966 + return (FAILURE);
899 967 }
900 968
901 -
902 969 /*
903 - * Get rid of the disabled list for the provider and get the converted
904 - * string for the entry. This is to prepare the string for a provider
905 - * that is in a package.
970 + * If it is loaded, unload it first. This does 2 ioctl calls:
971 + * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED.
906 972 */
907 - free_mechlist(pent->dislist);
908 - pent->dis_count = 0;
909 - pent->dislist = NULL;
910 - str = ent2str(pent);
911 - free_entry(pent);
912 - if (str == NULL) {
913 - cryptoerror(LOG_STDERR, gettext("internal error."));
914 - return (FAILURE);
915 - }
916 - (void) snprintf(strbuf, sizeof (strbuf), "%s%s", "#", str);
917 - free(str);
918 -
919 - /* If it is not loaded, unload it first */
920 - if (check_active_for_soft(provname, &is_active) == FAILURE) {
921 - return (FAILURE);
922 - } else if ((is_active == B_TRUE) &&
923 - (unload_kef_soft(provname, B_TRUE) == FAILURE)) {
973 + if (unload_kef_soft(provname) == FAILURE) {
924 974 cryptoerror(LOG_STDERR,
925 - gettext("failed to uninstall %s.\n"), provname);
975 + gettext("failed to unload %s during uninstall.\n"),
976 + provname);
926 977 return (FAILURE);
927 978 }
928 979
929 980 /*
930 - * Remove the entry from the config file. If the provider to be
931 - * uninstalled is in a package, just comment it off.
981 + * Inform kernel to remove the configuration of this software module.
932 982 */
933 - if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
934 - err = errno;
935 - cryptoerror(LOG_STDERR,
936 - gettext("failed to update the configuration - %s"),
937 - strerror(err));
938 - cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
939 - return (FAILURE);
940 - }
941 983
942 - if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
943 - err = errno;
944 - cryptoerror(LOG_STDERR,
945 - gettext("failed to lock the configuration - %s"),
946 - strerror(err));
947 - (void) fclose(pfile);
984 + /* Setup ioctl() parameter */
985 + pent = getent_kef(provname, NULL, NULL);
986 + if (pent != NULL) { /* in kcf.conf */
987 + in_kcfconf = B_TRUE;
988 + free_mechlist(pent->suplist);
989 + pent->suplist = NULL;
990 + pent->sup_count = 0;
991 + } else if ((pent = create_entry(provname)) == NULL) {
992 + cryptoerror(LOG_STDERR, gettext("out of memory."));
948 993 return (FAILURE);
949 994 }
950 -
951 - /*
952 - * Create a temporary file in the /etc/crypto directory to save
953 - * the new configuration file first.
954 - */
955 - (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
956 - if (mkstemp(tmpfile_name) == -1) {
957 - err = errno;
958 - cryptoerror(LOG_STDERR,
959 - gettext("failed to create a temporary file - %s"),
960 - strerror(err));
961 - (void) fclose(pfile);
995 + if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
996 + free_entry(pent);
962 997 return (FAILURE);
963 998 }
964 999
965 - if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
966 - err = errno;
967 - cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
968 - tmpfile_name, strerror(err));
969 - if (unlink(tmpfile_name) != 0) {
970 - err = errno;
971 - cryptoerror(LOG_STDERR, gettext(
972 - "(Warning) failed to remove %s: %s"), tmpfile_name,
973 - strerror(err));
974 - }
975 - (void) fclose(pfile);
1000 + /* Open the /dev/cryptoadm device */
1001 + if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
1002 + int err = errno;
1003 + cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
1004 + ADMIN_IOCTL_DEVICE, strerror(err));
1005 + free_entry(pent);
1006 + free(pload_soft_conf);
976 1007 return (FAILURE);
977 1008 }
978 1009
979 - /*
980 - * Loop thru the config file. If the kernel software provider
981 - * to be uninstalled is in a package, just comment it off.
982 - */
983 - in_package = B_FALSE;
984 - while (fgets(buffer, BUFSIZ, pfile) != NULL) {
985 - found = B_FALSE;
986 - if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
987 - buffer[0] == '\t')) {
988 - if (strstr(buffer, " Start ") != NULL) {
989 - in_package = B_TRUE;
990 - } else if (strstr(buffer, " End ") != NULL) {
991 - in_package = B_FALSE;
992 - } else if (buffer[0] != '#') {
993 - (void) strlcpy(buffer2, buffer, BUFSIZ);
994 -
995 - /* get rid of trailing '\n' */
996 - len = strlen(buffer2);
997 - if (buffer2[len-1] == '\n') {
998 - len--;
999 - }
1000 - buffer2[len] = '\0';
1001 -
1002 - if ((name = strtok(buffer2, SEP_COLON))
1003 - == NULL) {
1004 - rc = FAILURE;
1005 - break;
1006 - } else if (strcmp(provname, name) == 0) {
1007 - found = B_TRUE;
1008 - }
1009 - }
1010 - }
1011 -
1012 - if (found) {
1013 - if (in_package) {
1014 - if (fputs(strbuf, pfile_tmp) == EOF) {
1015 - rc = FAILURE;
1016 - }
1017 - }
1018 - } else {
1019 - if (fputs(buffer, pfile_tmp) == EOF) {
1020 - rc = FAILURE;
1021 - }
1022 - }
1023 -
1024 - if (rc == FAILURE) {
1025 - break;
1026 - }
1027 - }
1028 -
1029 - if (rc == FAILURE) {
1030 - cryptoerror(LOG_STDERR, gettext("write error."));
1031 - (void) fclose(pfile);
1032 - (void) fclose(pfile_tmp);
1033 - if (unlink(tmpfile_name) != 0) {
1034 - err = errno;
1035 - cryptoerror(LOG_STDERR, gettext(
1036 - "(Warning) failed to remove %s: %s"), tmpfile_name,
1037 - strerror(err));
1038 - }
1010 + if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG,
1011 + pload_soft_conf) == -1) {
1012 + cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1013 + strerror(errno));
1014 + free_entry(pent);
1015 + free(pload_soft_conf);
1016 + (void) close(fd);
1039 1017 return (FAILURE);
1040 1018 }
1041 1019
1042 - (void) fclose(pfile);
1043 - if (fclose(pfile_tmp) != 0) {
1044 - err = errno;
1045 - cryptoerror(LOG_STDERR,
1046 - gettext("failed to close %s: %s"), tmpfile_name,
1047 - strerror(err));
1020 + if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
1021 + cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d",
1022 + pload_soft_conf->sc_return_value);
1023 + free_entry(pent);
1024 + free(pload_soft_conf);
1025 + (void) close(fd);
1048 1026 return (FAILURE);
1049 1027 }
1050 1028
1051 - /* Now update the real config file */
1052 - if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
1053 - err = errno;
1054 - cryptoerror(LOG_STDERR,
1055 - gettext("failed to update the configuration - %s"),
1056 - strerror(err));
1057 - cryptodebug("failed to rename %1$s to %2$s: %3$s", tmpfile,
1058 - _PATH_KCF_CONF, strerror(err));
1059 - rc = FAILURE;
1060 - } else if (chmod(_PATH_KCF_CONF,
1061 - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1062 - err = errno;
1063 - cryptoerror(LOG_STDERR,
1064 - gettext("failed to update the configuration - %s"),
1065 - strerror(err));
1066 - cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
1067 - strerror(err));
1068 - rc = FAILURE;
1069 - } else {
1070 - rc = SUCCESS;
1071 - }
1029 + /* ioctl cleanup */
1030 + free(pload_soft_conf);
1031 + (void) close(fd);
1072 1032
1073 - if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1074 - err = errno;
1075 - cryptoerror(LOG_STDERR, gettext(
1076 - "(Warning) failed to remove %s: %s"), tmpfile_name,
1077 - strerror(err));
1033 +
1034 + /* Finally, remove entry from kcf.conf, if present */
1035 + if (in_kcfconf && (pent != NULL)) {
1036 + rc = update_kcfconf(pent, DELETE_MODE);
1078 1037 }
1079 1038
1039 + free_entry(pent);
1080 1040 return (rc);
1081 -
1082 1041 }
1083 1042
1084 1043
1044 +/*
1045 + * Implement the "cryptoadm refresh" command for global zones.
1046 + * That is, send the current contents of kcf.conf to the kernel via ioctl().
1047 + */
1085 1048 int
1086 1049 refresh(void)
1087 1050 {
1088 - crypto_get_soft_list_t *psoftlist_kernel = NULL;
1089 1051 crypto_load_soft_config_t *pload_soft_conf = NULL;
1090 1052 crypto_load_soft_disabled_t *pload_soft_dis = NULL;
1091 1053 crypto_load_dev_disabled_t *pload_dev_dis = NULL;
1092 - entrylist_t *pdevlist = NULL;
1093 - entrylist_t *psoftlist = NULL;
1094 - entrylist_t *ptr;
1095 - boolean_t found;
1096 - char *psoftname;
1097 - int fd;
1098 - int rc = SUCCESS;
1099 - int i;
1054 + entrylist_t *pdevlist = NULL;
1055 + entrylist_t *psoftlist = NULL;
1056 + entrylist_t *ptr;
1057 + int fd = -1;
1058 + int rc = SUCCESS;
1059 + int err;
1100 1060
1101 - if (get_soft_list(&psoftlist_kernel) == FAILURE) {
1102 - cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
1103 - "software provider list from kernel."));
1104 - return (FAILURE);
1105 - }
1106 -
1107 1061 if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
1108 1062 cryptoerror(LOG_ERR, "failed to retrieve the providers' "
1109 1063 "information from the configuration file - %s.",
1110 1064 _PATH_KCF_CONF);
1111 1065 return (FAILURE);
1112 1066 }
1113 1067
1114 - /*
1115 - * If a kernel software provider is in kernel, but it is not in the
1116 - * kcf.conf file, it must have been pkgrm'ed and needs to be unloaded
1117 - * now.
1118 - */
1119 - if (psoftlist_kernel->sl_soft_count > 0) {
1120 - psoftname = psoftlist_kernel->sl_soft_names;
1121 - for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
1122 - ptr = psoftlist;
1123 - found = B_FALSE;
1124 - while (ptr != NULL) {
1125 - if (strcmp(psoftname, ptr->pent->name) == 0) {
1126 - found = B_TRUE;
1127 - break;
1128 - }
1129 - ptr = ptr->next;
1130 - }
1131 -
1132 - if (!found) {
1133 - rc = unload_kef_soft(psoftname, B_FALSE);
1134 - if (rc == FAILURE) {
1135 - cryptoerror(LOG_ERR, gettext(
1136 - "WARNING - the provider %s is "
1137 - "still in kernel."), psoftname);
1138 - }
1139 - }
1140 - psoftname = psoftname + strlen(psoftname) + 1;
1141 - }
1142 - }
1143 - free(psoftlist_kernel);
1144 -
1145 1068 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
1146 1069 err = errno;
1147 1070 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
1148 1071 ADMIN_IOCTL_DEVICE, strerror(err));
1149 1072 free(psoftlist);
1150 1073 free(pdevlist);
1151 1074 return (FAILURE);
1152 1075 }
1153 1076
1154 1077 /*
1155 - * For each software module, pass two sets of information to kernel
1156 - * - the supported list and the disabled list
1078 + * For each software provider module, pass two sets of information to
1079 + * the kernel: the supported list and the disabled list.
1157 1080 */
1158 - ptr = psoftlist;
1159 - while (ptr != NULL) {
1081 + for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) {
1082 + entry_t *pent = ptr->pent;
1083 +
1160 1084 /* load the supported list */
1161 - if ((pload_soft_conf = setup_soft_conf(ptr->pent)) == NULL) {
1085 + if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
1086 + cryptodebug("setup_soft_conf() failed");
1162 1087 rc = FAILURE;
1163 1088 break;
1164 1089 }
1165 1090
1091 + if (!pent->load) { /* unloaded--mark as loaded */
1092 + pent->load = B_TRUE;
1093 + rc = update_kcfconf(pent, MODIFY_MODE);
1094 + if (rc != SUCCESS) {
1095 + free(pload_soft_conf);
1096 + break;
1097 + }
1098 + }
1099 +
1166 1100 if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf)
1167 1101 == -1) {
1168 1102 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1169 1103 strerror(errno));
1170 1104 free(pload_soft_conf);
1171 1105 rc = FAILURE;
1172 1106 break;
1173 1107 }
1174 1108
1175 1109 if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
1176 1110 cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
1177 1111 "return_value = %d",
1178 1112 pload_soft_conf->sc_return_value);
1179 1113 free(pload_soft_conf);
1180 1114 rc = FAILURE;
1181 1115 break;
1182 1116 }
1183 1117
1118 + free(pload_soft_conf);
1119 +
1184 1120 /* load the disabled list */
1185 1121 if (ptr->pent->dis_count != 0) {
1186 1122 pload_soft_dis = setup_soft_dis(ptr->pent);
1187 1123 if (pload_soft_dis == NULL) {
1124 + cryptodebug("setup_soft_dis() failed");
1125 + free(pload_soft_dis);
1188 1126 rc = FAILURE;
1189 1127 break;
1190 1128 }
1191 1129
1192 1130 if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED,
1193 1131 pload_soft_dis) == -1) {
1194 1132 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1195 1133 "failed: %s", strerror(errno));
1196 1134 free(pload_soft_dis);
1197 1135 rc = FAILURE;
1198 1136 break;
1199 1137 }
1200 1138
1201 1139 if (pload_soft_dis->sd_return_value !=
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
1202 1140 CRYPTO_SUCCESS) {
1203 1141 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1204 1142 "return_value = %d",
1205 1143 pload_soft_dis->sd_return_value);
1206 1144 free(pload_soft_dis);
1207 1145 rc = FAILURE;
1208 1146 break;
1209 1147 }
1210 1148 free(pload_soft_dis);
1211 1149 }
1212 -
1213 - free(pload_soft_conf);
1214 - ptr = ptr->next;
1215 1150 }
1216 1151
1217 1152 if (rc != SUCCESS) {
1218 1153 (void) close(fd);
1219 1154 return (rc);
1220 1155 }
1221 1156
1222 1157
1223 - /* Pass the disabledlist information for Device to kernel */
1224 - ptr = pdevlist;
1225 - while (ptr != NULL) {
1158 + /*
1159 + * For each hardware provider module, pass the disabled list
1160 + * information to the kernel.
1161 + */
1162 + for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) {
1226 1163 /* load the disabled list */
1227 1164 if (ptr->pent->dis_count != 0) {
1228 1165 pload_dev_dis = setup_dev_dis(ptr->pent);
1229 1166 if (pload_dev_dis == NULL) {
1230 1167 rc = FAILURE;
1231 1168 break;
1232 1169 }
1233 1170
1234 1171 if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis)
1235 1172 == -1) {
1236 1173 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
1237 1174 "failed: %s", strerror(errno));
1238 1175 free(pload_dev_dis);
1239 1176 rc = FAILURE;
1240 1177 break;
1241 1178 }
1242 1179
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
1243 1180 if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
1244 1181 cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
1245 1182 "return_value = %d",
1246 1183 pload_dev_dis->dd_return_value);
1247 1184 free(pload_dev_dis);
1248 1185 rc = FAILURE;
1249 1186 break;
1250 1187 }
1251 1188 free(pload_dev_dis);
1252 1189 }
1253 -
1254 - ptr = ptr->next;
1255 1190 }
1256 1191
1257 1192 (void) close(fd);
1258 1193 return (rc);
1259 1194 }
1260 1195
1261 1196 /*
1262 1197 * Unload the kernel software provider. Before calling this function, the
1263 - * caller should check if the provider is in the config file and if it
1264 - * is kernel. This routine makes 3 ioctl calls to remove it from kernel
1265 - * completely. The argument do_check set to B_FALSE means that the
1266 - * caller knows the provider is not the config file and hence the check
1267 - * is skipped.
1198 + * caller should check to see if the provider is in the kernel.
1199 + *
1200 + * This routine makes 2 ioctl calls to remove it completely from the kernel:
1201 + * CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module
1202 + * CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list
1203 + *
1204 + * This implements part of "cryptoadm unload" and "cryptoadm uninstall".
1268 1205 */
1269 1206 int
1270 -unload_kef_soft(char *provname, boolean_t do_check)
1207 +unload_kef_soft(char *provname)
1271 1208 {
1272 - crypto_unload_soft_module_t *punload_soft = NULL;
1273 - crypto_load_soft_config_t *pload_soft_conf = NULL;
1209 + crypto_unload_soft_module_t *punload_soft = NULL;
1274 1210 crypto_load_soft_disabled_t *pload_soft_dis = NULL;
1275 - entry_t *pent = NULL;
1276 - int fd;
1211 + entry_t *pent = NULL;
1212 + int fd = -1;
1213 + int err;
1277 1214
1278 1215 if (provname == NULL) {
1279 1216 cryptoerror(LOG_STDERR, gettext("internal error."));
1280 1217 return (FAILURE);
1281 1218 }
1282 1219
1283 - if (!do_check) {
1220 + pent = getent_kef(provname, NULL, NULL);
1221 + if (pent == NULL) { /* not in kcf.conf */
1284 1222 /* Construct an entry using the provname */
1285 - pent = calloc(1, sizeof (entry_t));
1223 + pent = create_entry(provname);
1286 1224 if (pent == NULL) {
1287 1225 cryptoerror(LOG_STDERR, gettext("out of memory."));
1288 1226 return (FAILURE);
1289 1227 }
1290 - (void) strlcpy(pent->name, provname, MAXNAMELEN);
1291 - } else if ((pent = getent_kef(provname)) == NULL) {
1292 - cryptoerror(LOG_STDERR, gettext("%s does not exist."),
1293 - provname);
1294 - return (FAILURE);
1295 1228 }
1296 1229
1297 1230 /* Open the admin_ioctl_device */
1298 1231 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
1299 1232 err = errno;
1300 1233 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
1301 1234 ADMIN_IOCTL_DEVICE, strerror(err));
1235 + free_entry(pent);
1302 1236 return (FAILURE);
1303 1237 }
1304 1238
1305 1239 /* Inform kernel to unload this software module */
1306 1240 if ((punload_soft = setup_unload_soft(pent)) == NULL) {
1241 + free_entry(pent);
1307 1242 (void) close(fd);
1308 1243 return (FAILURE);
1309 1244 }
1310 1245
1311 1246 if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) {
1312 1247 cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
1313 1248 strerror(errno));
1314 1249 free_entry(pent);
1315 1250 free(punload_soft);
1316 1251 (void) close(fd);
1317 1252 return (FAILURE);
1318 1253 }
1319 1254
1320 1255 if (punload_soft->sm_return_value != CRYPTO_SUCCESS) {
1321 1256 cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = "
1322 1257 "%d", punload_soft->sm_return_value);
1323 1258 /*
1324 1259 * If the return value is CRYPTO_UNKNOWN_PROVIDER, it means
1325 1260 * that the provider is not registered yet. Should just
1326 1261 * continue.
1327 1262 */
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1328 1263 if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) {
1329 1264 free_entry(pent);
1330 1265 free(punload_soft);
1331 1266 (void) close(fd);
1332 1267 return (FAILURE);
1333 1268 }
1334 1269 }
1335 1270
1336 1271 free(punload_soft);
1337 1272
1338 - /*
1339 - * Inform kernel to remove the configuration of this software
1340 - * module.
1341 - */
1342 - free_mechlist(pent->suplist);
1343 - pent->suplist = NULL;
1344 - pent->sup_count = 0;
1345 - if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
1346 - free_entry(pent);
1347 - (void) close(fd);
1348 - return (FAILURE);
1349 - }
1350 -
1351 - if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
1352 - cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1353 - strerror(errno));
1354 - free_entry(pent);
1355 - free(pload_soft_conf);
1356 - (void) close(fd);
1357 - return (FAILURE);
1358 - }
1359 -
1360 - if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
1361 - cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl return_value = "
1362 - "%d", pload_soft_conf->sc_return_value);
1363 - free_entry(pent);
1364 - free(pload_soft_conf);
1365 - (void) close(fd);
1366 - return (FAILURE);
1367 - }
1368 -
1369 - free(pload_soft_conf);
1370 -
1371 1273 /* Inform kernel to remove the disabled entries if any */
1372 1274 if (pent->dis_count == 0) {
1373 1275 free_entry(pent);
1374 1276 (void) close(fd);
1375 1277 return (SUCCESS);
1376 1278 } else {
1377 1279 free_mechlist(pent->dislist);
1378 1280 pent->dislist = NULL;
1379 1281 pent->dis_count = 0;
1380 1282 }
1381 1283
1382 1284 if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
1383 1285 free_entry(pent);
1384 1286 (void) close(fd);
1385 1287 return (FAILURE);
1386 1288 }
1387 1289
1388 1290 /* pent is no longer needed; free it */
1389 1291 free_entry(pent);
1390 1292
1391 1293 if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
1392 1294 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
1393 1295 strerror(errno));
1394 1296 free(pload_soft_dis);
1395 1297 (void) close(fd);
1396 1298 return (FAILURE);
1397 1299 }
1398 1300
1399 1301 if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
1400 1302 cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
1401 1303 "%d", pload_soft_dis->sd_return_value);
1402 1304 free(pload_soft_dis);
1403 1305 (void) close(fd);
1404 1306 return (FAILURE);
1405 1307 }
1406 1308
1407 1309 free(pload_soft_dis);
1408 1310 (void) close(fd);
1409 1311 return (SUCCESS);
1410 1312 }
1411 1313
1412 1314
1413 1315 /*
1414 1316 * Check if a hardware provider is valid. If it is valid, returns its device
1415 1317 * name, instance number and the number of mechanisms it supports.
1416 1318 */
1417 1319 static int
1418 1320 check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount)
1419 1321 {
1420 1322 crypto_get_dev_list_t *dev_list = NULL;
1421 1323 int i;
1422 1324
1423 1325 if (provname == NULL) {
1424 1326 return (FAILURE);
1425 1327 }
1426 1328
1427 1329 /* First, get the device name and the instance number from provname */
1428 1330 if (split_hw_provname(provname, pname, pnum) == FAILURE) {
1429 1331 return (FAILURE);
1430 1332 }
1431 1333
1432 1334 /*
1433 1335 * Get the complete device list from kernel and check if this provider
1434 1336 * is in the list.
1435 1337 */
1436 1338 if (get_dev_list(&dev_list) == FAILURE) {
1437 1339 return (FAILURE);
1438 1340 }
1439 1341
1440 1342 for (i = 0; i < dev_list->dl_dev_count; i++) {
1441 1343 if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) &&
1442 1344 (dev_list->dl_devs[i].le_dev_instance == *pnum)) {
1443 1345 break;
1444 1346 }
1445 1347 }
1446 1348
1447 1349 if (i == dev_list->dl_dev_count) {
1448 1350 /* didn't find this provider in the kernel device list */
1449 1351 cryptoerror(LOG_STDERR, gettext("%s does not exist."),
1450 1352 provname);
1451 1353 free(dev_list);
1452 1354 return (FAILURE);
1453 1355 }
1454 1356
1455 1357 /* This provider is valid. Get its mechanism count */
1456 1358 *pcount = dev_list->dl_devs[i].le_mechanism_count;
1457 1359
1458 1360 free(dev_list);
1459 1361 return (SUCCESS);
1460 1362 }
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX