4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
28 #include <sys/types.h>
40 #include <sys/crypto/elfsign.h>
41 #include <cryptoutil.h>
43 #include <security/cryptoki.h>
44 #include "pkcs11Global.h"
45 #include "pkcs11Conf.h"
46 #include "pkcs11Slot.h"
47 #include "metaGlobal.h"
50 * Fastpath is used when there is only one slot available from a single provider
51 * plugged into the framework this is the common case.
52 * These globals are used to track the function pointers and policy when
53 * the fast-path is activated.
54 * This will need to be revisted if per-slot policy is ever
57 boolean_t purefastpath
= B_FALSE
;
58 boolean_t policyfastpath
= B_FALSE
;
59 CK_FUNCTION_LIST_PTR fast_funcs
= NULL
;
60 CK_SLOT_ID fast_slot
= 0;
61 boolean_t metaslot_enabled
= B_FALSE
;
62 boolean_t metaslot_auto_key_migrate
= B_FALSE
;
63 metaslot_config_t metaslot_config
;
64 void (*Tmp_GetThreshold
)(void *) = NULL
;
65 cipher_mechs_threshold_t meta_mechs_threshold
[MAX_NUM_THRESHOLD
];
67 static const char *conf_err
= "See cryptoadm(1M). Skipping this plug-in.";
70 * Set up metaslot for the framework using either user configuration
71 * or system wide configuration options
73 * Also sets up the global "slottable" to have the first slot be metaslot.
76 setup_metaslot(uentry_t
*metaslot_entry
) {
78 CK_MECHANISM_TYPE_PTR prov_pol_mechs
= NULL
;
79 pkcs11_slot_t
*cur_slot
;
81 /* process policies for mechanisms */
82 if ((metaslot_entry
) && (metaslot_entry
->count
> 0)) {
83 rv
= pkcs11_mech_parse(metaslot_entry
->policylist
,
84 &prov_pol_mechs
, metaslot_entry
->count
);
86 if (rv
== CKR_HOST_MEMORY
) {
88 "libpkcs11: Could not parse configuration,"
89 "out of memory. Cannot continue parsing "
90 "%s.\n", _PATH_PKCS11_CONF
);
92 } else if (rv
== CKR_MECHANISM_INVALID
) {
94 * Configuration file is corrupted for metaslot
97 "libpkcs11: Policy invalid or corrupted "
98 "for metaslot. Use cryptoadm(1M) to fix "
99 "this. Disabling metaslot functionality.\n");
100 metaslot_enabled
= B_FALSE
;
106 * Check for metaslot policy. If all mechanisms are
107 * disabled, disable metaslot since there is nothing
108 * interesting for it to do
110 if ((metaslot_entry
) && (metaslot_entry
->flag_enabledlist
) &&
111 (prov_pol_mechs
== NULL
)) {
112 metaslot_enabled
= B_FALSE
;
117 * save system wide value for metaslot's keystore.
118 * If either slot description or token label is specified by
119 * the user, the system wide value for both is ignored.
121 if ((metaslot_entry
) &&
122 (!metaslot_config
.keystore_token_specified
) &&
123 (!metaslot_config
.keystore_slot_specified
)) {
125 * blank_str is used for comparing with token label,
126 * and slot description, make sure it is better than
129 char blank_str
[TOKEN_LABEL_SIZE
+ SLOT_DESCRIPTION_SIZE
];
131 bzero(blank_str
, sizeof (blank_str
));
133 if (memcmp(metaslot_entry
->metaslot_ks_token
,
134 blank_str
, TOKEN_LABEL_SIZE
) != 0) {
135 metaslot_config
.keystore_token_specified
= B_TRUE
;
137 (char *)metaslot_config
.keystore_token
,
138 (const char *)metaslot_entry
->metaslot_ks_token
,
142 if (memcmp(metaslot_entry
->metaslot_ks_slot
,
143 blank_str
, SLOT_DESCRIPTION_SIZE
) != 0) {
144 metaslot_config
.keystore_slot_specified
= B_TRUE
;
146 (char *)metaslot_config
.keystore_slot
,
147 (const char *)metaslot_entry
->metaslot_ks_slot
,
148 SLOT_DESCRIPTION_SIZE
);
152 /* check system-wide value for auto_key_migrate */
153 if (metaslot_config
.auto_key_migrate_specified
) {
154 /* take user's specified value */
155 metaslot_auto_key_migrate
= metaslot_config
.auto_key_migrate
;
157 if (metaslot_entry
) {
158 /* use system-wide default */
159 metaslot_auto_key_migrate
=
160 metaslot_entry
->flag_metaslot_auto_key_migrate
;
163 * there's no system wide metaslot entry,
164 * default auto_key_migrate to true
166 metaslot_auto_key_migrate
= B_TRUE
;
171 /* Make first slotID be 0, for metaslot. */
172 slottable
->st_first
= 0;
174 /* Set up the slottable entry for metaslot */
175 slottable
->st_slots
[0] = NULL
;
176 cur_slot
= calloc(1, sizeof (pkcs11_slot_t
));
177 if (cur_slot
== NULL
) {
178 rv
= CKR_HOST_MEMORY
;
181 cur_slot
->sl_wfse_state
= WFSE_CLEAR
;
182 cur_slot
->sl_enabledpol
= B_FALSE
;
183 cur_slot
->sl_no_wfse
= B_FALSE
;
184 (void) pthread_mutex_init(&cur_slot
->sl_mutex
, NULL
);
187 * The metaslot entry was prealloc'd by
188 * pkcs11_slottable_increase()
190 (void) pthread_mutex_lock(&slottable
->st_mutex
);
191 slottable
->st_slots
[0] = cur_slot
;
192 (void) pthread_mutex_unlock(&slottable
->st_mutex
);
194 (void) pthread_mutex_lock(&cur_slot
->sl_mutex
);
195 cur_slot
->sl_id
= METASLOT_SLOTID
;
196 cur_slot
->sl_func_list
= &metaslot_functionList
;
197 if (metaslot_entry
) {
198 cur_slot
->sl_enabledpol
= metaslot_entry
->flag_enabledlist
;
199 cur_slot
->sl_pol_count
= metaslot_entry
->count
;
201 /* if no metaslot entry, assume all mechs are enabled */
202 cur_slot
->sl_enabledpol
= B_FALSE
;
203 cur_slot
->sl_pol_count
= 0;
205 cur_slot
->sl_pol_mechs
= prov_pol_mechs
;
206 cur_slot
->sl_dldesc
= NULL
; /* not applicable */
207 cur_slot
->sl_prov_id
= 0;
208 (void) pthread_mutex_unlock(&cur_slot
->sl_mutex
);
210 /* Call the meta_Initialize() to initialize metaslot */
211 rv
= meta_Initialize(NULL
);
214 "libpkcs11: Can't initialize metaslot (%s)",
215 pkcs11_strerror(rv
));
222 metaslot_enabled
= B_FALSE
;
223 slottable
->st_slots
[0] = NULL
;
226 (void) pthread_mutex_destroy(&cur_slot
->sl_mutex
);
233 * For each provider found in pkcs11.conf: expand $ISA if necessary,
234 * verify the module is signed, load the provider, find all of its
235 * slots, and store the function list and disabled policy.
237 * This function requires that the uentrylist_t and pkcs11_slottable_t
238 * already have memory allocated, and that the uentrylist_t is already
239 * populated with provider and policy information.
241 * pInitArgs can be set to NULL, but is normally the same value
242 * the framework's C_Initialize() was called with.
244 * Unless metaslot is explicitly disabled, it is setup when all other
245 * providers are loaded.
248 pkcs11_slot_mapping(uentrylist_t
*pplist
, CK_VOID_PTR pInitArgs
)
251 CK_RV prov_rv
; /* Provider's return code */
253 CK_RV (*Tmp_C_GetFunctionList
)(CK_FUNCTION_LIST_PTR_PTR
);
254 CK_FUNCTION_LIST_PTR prov_funcs
= NULL
; /* Provider's function list */
255 CK_ULONG prov_slot_count
; /* Number of slots */
256 CK_SLOT_ID slot_id
; /* slotID assigned for framework */
257 CK_SLOT_ID_PTR prov_slots
= NULL
; /* Provider's slot list */
258 /* Enabled or Disabled policy */
259 CK_MECHANISM_TYPE_PTR prov_pol_mechs
= NULL
;
262 char *isa
, *fullpath
= NULL
, *dl_error
;
264 uint_t prov_count
= 0;
265 pkcs11_slot_t
*cur_slot
;
268 uentry_t
*metaslot_entry
= NULL
;
269 /* number of slots in the framework, not including metaslot */
270 uint_t slot_count
= 0;
274 /* Loop through all of the provider listed in pkcs11.conf */
275 while (phead
!= NULL
) {
276 if (!strcasecmp(phead
->puent
->name
, "metaslot")) {
278 * Skip standard processing for metaslot
279 * entry since it is not an actual library
280 * that can be dlopened.
281 * It will be initialized later.
283 if (metaslot_entry
!= NULL
) {
285 "libpkcs11: multiple entries for metaslot "
286 "detected. All but the first entry will "
289 metaslot_entry
= phead
->puent
;
294 if (!strcasecmp(phead
->puent
->name
, FIPS_KEYWORD
)) {
296 * Skip standard processing for fips-140
297 * entry since it is not an actual library
298 * that can be dlopened.
303 /* Check for Instruction Set Architecture indicator */
304 if ((isa
= strstr(phead
->puent
->name
, PKCS11_ISA
)) != NULL
) {
305 /* Substitute the architecture dependent path */
306 len
= strlen(phead
->puent
->name
) -
308 strlen(PKCS11_ISA_DIR
) + 1;
309 if ((fullpath
= (char *)malloc(len
)) == NULL
) {
311 "libpksc11: parsing %s, out of memory. "
312 "Cannot continue parsing.",
314 rv
= CKR_HOST_MEMORY
;
318 isa
+= strlen(PKCS11_ISA
);
319 (void) snprintf(fullpath
, len
, "%s%s%s",
320 phead
->puent
->name
, PKCS11_ISA_DIR
, isa
);
321 } else if ((fullpath
= strdup(phead
->puent
->name
)) == 0) {
323 "libpkcs11: parsing %s, out of memory. "
324 "Cannot continue parsing.",
326 rv
= CKR_HOST_MEMORY
;
331 * Open the provider. We assume all of our plugins have
332 * their symbols properly defined, so the use of RTLD_NOW
333 * to flush out errors immediately is not necessary.
335 * Note that for proper operation, all plugins must be
336 * built with direct bindings enabled.
338 dldesc
= dlopen(fullpath
, RTLD_LAZY
);
341 * If we failed to load it, we will just skip this
342 * provider and move on to the next one.
344 if (dldesc
== NULL
) {
345 dl_error
= dlerror();
347 "libpkcs11: Cannot load PKCS#11 library %s. "
349 fullpath
, dl_error
!= NULL
? dl_error
: "Unknown",
354 /* Get the pointer to provider's C_GetFunctionList() */
355 Tmp_C_GetFunctionList
=
356 (CK_RV(*)())dlsym(dldesc
, "C_GetFunctionList");
359 * If we failed to get the pointer to C_GetFunctionList(),
360 * skip this provider and continue to the next one.
362 if (Tmp_C_GetFunctionList
== NULL
) {
364 "libpkcs11: Could not dlsym() C_GetFunctionList() "
365 "for %s. May not be a PKCS#11 library. %s",
367 (void) dlclose(dldesc
);
372 /* Get the provider's function list */
373 prov_rv
= Tmp_C_GetFunctionList(&prov_funcs
);
376 * If we failed to get the provider's function list,
377 * skip this provider and continue to the next one.
379 if (prov_rv
!= CKR_OK
) {
381 "libpkcs11: Could not get function list for %s. "
383 fullpath
, conf_err
, pkcs11_strerror(prov_rv
));
384 (void) dlclose(dldesc
);
388 /* Initialize this provider */
389 prov_rv
= prov_funcs
->C_Initialize(pInitArgs
);
392 * If we failed to initialize this provider,
393 * skip this provider and continue to the next one.
395 if ((prov_rv
!= CKR_OK
) &&
396 (prov_rv
!= CKR_CRYPTOKI_ALREADY_INITIALIZED
)) {
398 "libpkcs11: Could not initialize %s. "
400 fullpath
, conf_err
, pkcs11_strerror(prov_rv
));
401 (void) dlclose(dldesc
);
406 * Make sure this provider is implementing the same
407 * major version, and at least the same minor version
410 prov_rv
= prov_funcs
->C_GetInfo(&prov_info
);
413 * If we can't verify that we are implementing the
414 * same major version, or if it is definitely not the same
415 * version, we need to skip this provider.
417 if ((prov_rv
!= CKR_OK
) ||
418 (prov_info
.cryptokiVersion
.major
!=
419 CRYPTOKI_VERSION_MAJOR
)) {
420 if (prov_rv
!= CKR_OK
) {
422 "libpkcs11: Could not verify version of "
423 "%s. %s Error: %s.", fullpath
,
424 conf_err
, pkcs11_strerror(prov_rv
));
427 "libpkcs11: Only CRYPTOKI major version "
428 "%d is supported. %s is major "
430 CRYPTOKI_VERSION_MAJOR
, fullpath
,
431 prov_info
.cryptokiVersion
.major
, conf_err
);
433 (void) prov_funcs
->C_Finalize(NULL
);
434 (void) dlclose(dldesc
);
439 * Warn the administrator (at debug) that a provider with
440 * a significantly older or newer version of
441 * CRYPTOKI is being used. It should not cause
442 * problems, but logging a warning makes it easier
445 if ((prov_info
.cryptokiVersion
.minor
<
446 CRYPTOKI_VERSION_WARN_MINOR
) ||
447 (prov_info
.cryptokiVersion
.minor
>
448 CRYPTOKI_VERSION_MINOR
)) {
449 cryptoerror(LOG_DEBUG
,
450 "libpkcs11: %s CRYPTOKI minor version, %d, may "
451 "not be compatible with minor version %d.",
452 fullpath
, prov_info
.cryptokiVersion
.minor
,
453 CRYPTOKI_VERSION_MINOR
);
457 * Find out how many slots this provider has,
458 * call with tokenPresent set to FALSE so all
459 * potential slots are returned.
461 prov_rv
= prov_funcs
->C_GetSlotList(FALSE
,
462 NULL
, &prov_slot_count
);
465 * If the call failed, or if no slots are returned,
466 * then skip this provider and continue to next one.
468 if (prov_rv
!= CKR_OK
) {
470 "libpksc11: Could not get slot list from %s. "
472 fullpath
, conf_err
, pkcs11_strerror(prov_rv
));
473 (void) prov_funcs
->C_Finalize(NULL
);
474 (void) dlclose(dldesc
);
478 if (prov_slot_count
== 0) {
479 cryptodebug("libpkcs11: No slots presented from %s. "
480 "Skipping this plug-in at this time.\n",
482 (void) prov_funcs
->C_Finalize(NULL
);
483 (void) dlclose(dldesc
);
487 /* Allocate memory for the slot list */
488 prov_slots
= calloc(prov_slot_count
, sizeof (CK_SLOT_ID
));
490 if (prov_slots
== NULL
) {
492 "libpkcs11: Could not allocate memory for "
493 "plug-in slots. Cannot continue parsing %s\n",
495 rv
= CKR_HOST_MEMORY
;
499 /* Get slot list from provider */
500 prov_rv
= prov_funcs
->C_GetSlotList(FALSE
,
501 prov_slots
, &prov_slot_count
);
503 /* if second call fails, drop this provider */
504 if (prov_rv
!= CKR_OK
) {
506 "libpkcs11: Second call to C_GetSlotList() for %s "
507 "failed. %s Error: %s.",
508 fullpath
, conf_err
, pkcs11_strerror(prov_rv
));
509 (void) prov_funcs
->C_Finalize(NULL
);
510 (void) dlclose(dldesc
);
515 * Parse the list of disabled or enabled mechanisms, will
516 * apply to each of the provider's slots.
518 if (phead
->puent
->count
> 0) {
519 rv
= pkcs11_mech_parse(phead
->puent
->policylist
,
520 &prov_pol_mechs
, phead
->puent
->count
);
522 if (rv
== CKR_HOST_MEMORY
) {
524 "libpkcs11: Could not parse configuration,"
525 "out of memory. Cannot continue parsing "
526 "%s.", _PATH_PKCS11_CONF
);
528 } else if (rv
== CKR_MECHANISM_INVALID
) {
530 * Configuration file is corrupted for this
534 "libpkcs11: Policy invalid or corrupted "
535 "for %s. Use cryptoadm(1M) to fix "
536 "this. Skipping this plug-in.",
538 (void) prov_funcs
->C_Finalize(NULL
);
539 (void) dlclose(dldesc
);
544 /* Allocate memory in our slottable for these slots */
545 rv
= pkcs11_slottable_increase(prov_slot_count
);
548 * If any error is returned, it will be memory related,
549 * so we need to abort the attempt at filling the
554 "libpkcs11: slottable could not increase. "
555 "Cannot continue parsing %s.",
560 /* Configure information for each new slot */
561 for (i
= 0; i
< prov_slot_count
; i
++) {
562 /* allocate slot in framework */
563 rv
= pkcs11_slot_allocate(&slot_id
);
566 "libpkcs11: Could not allocate "
567 "new slot. Cannot continue parsing %s.",
572 cur_slot
= slottable
->st_slots
[slot_id
];
573 (void) pthread_mutex_lock(&cur_slot
->sl_mutex
);
574 cur_slot
->sl_id
= prov_slots
[i
];
575 cur_slot
->sl_func_list
= prov_funcs
;
576 cur_slot
->sl_enabledpol
=
577 phead
->puent
->flag_enabledlist
;
578 cur_slot
->sl_pol_mechs
= prov_pol_mechs
;
579 cur_slot
->sl_pol_count
= phead
->puent
->count
;
580 cur_slot
->sl_norandom
= phead
->puent
->flag_norandom
;
581 cur_slot
->sl_dldesc
= dldesc
;
582 cur_slot
->sl_prov_id
= prov_count
+ 1;
583 (void) pthread_mutex_unlock(&cur_slot
->sl_mutex
);
587 * Get the pointer to private interface _SUNW_GetThreshold()
591 if (Tmp_GetThreshold
== NULL
) {
593 (void(*)())dlsym(dldesc
, "_SUNW_GetThreshold");
595 /* Get the threshold values for the supported mechs */
596 if (Tmp_GetThreshold
!= NULL
) {
597 (void) memset(meta_mechs_threshold
, 0,
598 sizeof (meta_mechs_threshold
));
599 Tmp_GetThreshold(meta_mechs_threshold
);
603 /* Set and reset values to process next provider */
607 Tmp_C_GetFunctionList
= NULL
;
610 if (fullpath
!= NULL
) {
614 if (prov_slots
!= NULL
) {
621 if (slot_count
== 0) {
623 * there's no other slot in the framework,
624 * there is nothing to do
626 goto config_complete
;
629 /* determine if metaslot should be enabled */
632 * Check to see if any environment variable is defined
633 * by the user for configuring metaslot. Users'
634 * setting always take precedence over the system wide
635 * setting. So, we will first check for any user's
636 * defined env variables before looking at the system-wide
639 get_user_metaslot_config();
641 /* no metaslot entry in /etc/crypto/pkcs11.conf */
642 if (!metaslot_entry
) {
644 * If user env variable indicates metaslot should be enabled,
645 * but there's no entry in /etc/crypto/pkcs11.conf for
646 * metaslot at all, will respect the user's defined value
648 if ((metaslot_config
.enabled_specified
) &&
649 (metaslot_config
.enabled
)) {
650 metaslot_enabled
= B_TRUE
;
653 if (!metaslot_config
.enabled_specified
) {
655 * take system wide value if
656 * it is not specified by user
659 = metaslot_entry
->flag_metaslot_enabled
;
661 metaslot_enabled
= metaslot_config
.enabled
;
667 * As long as the user or system configuration file does not
668 * disable metaslot, it will be enabled regardless of the
669 * number of slots plugged into the framework. Therefore,
670 * metaslot is enabled even when there's only one slot
671 * plugged into the framework. This is necessary for
672 * presenting a consistent token label view to applications.
674 * However, for the case where there is only 1 slot plugged into
675 * the framework, we can use "fastpath".
677 * "fastpath" will pass all of the application's requests
678 * directly to the underlying provider. Only when policy is in
679 * effect will we need to keep slotID around.
681 * When metaslot is enabled, and fastpath is enabled,
682 * all the metaslot processing will be skipped.
683 * When there is only 1 slot, there's
684 * really not much metaslot can do in terms of combining functionality
685 * of different slots, and object migration.
689 /* check to see if fastpath can be used */
690 if (slottable
->st_last
== slottable
->st_first
) {
692 cur_slot
= slottable
->st_slots
[slottable
->st_first
];
694 (void) pthread_mutex_lock(&cur_slot
->sl_mutex
);
696 if ((cur_slot
->sl_pol_count
== 0) &&
697 (!cur_slot
->sl_enabledpol
) && (!cur_slot
->sl_norandom
)) {
698 /* No policy is in effect, don't need slotid */
699 fast_funcs
= cur_slot
->sl_func_list
;
700 purefastpath
= B_TRUE
;
702 fast_funcs
= cur_slot
->sl_func_list
;
703 fast_slot
= slottable
->st_first
;
704 policyfastpath
= B_TRUE
;
707 (void) pthread_mutex_unlock(&cur_slot
->sl_mutex
);
710 if ((purefastpath
|| policyfastpath
) && (!metaslot_enabled
)) {
711 goto config_complete
;
715 * If we get here, there are more than 2 slots in the framework,
716 * we need to set up metaslot if it is enabled
718 if (metaslot_enabled
) {
719 rv
= setup_metaslot(metaslot_entry
);
732 * This cleanup code is only exercised when a major,
733 * unrecoverable error like "out of memory".
735 if (prov_funcs
!= NULL
) {
736 (void) prov_funcs
->C_Finalize(NULL
);
738 if (dldesc
!= NULL
) {
739 (void) dlclose(dldesc
);
741 if (fullpath
!= NULL
) {
745 if (prov_slots
!= NULL
) {
754 * pkcs11_mech_parse will take hex mechanism ids, as a list of
755 * strings, and convert them to CK_MECHANISM_TYPE_PTR.
758 pkcs11_mech_parse(umechlist_t
*str_list
, CK_MECHANISM_TYPE_PTR
*mech_list
,
761 CK_MECHANISM_TYPE_PTR tmp_list
;
762 umechlist_t
*shead
= str_list
;
764 tmp_list
= malloc(mech_count
* sizeof (CK_MECHANISM_TYPE
));
766 if (tmp_list
== NULL
) {
767 cryptoerror(LOG_ERR
, "libpkcs11: parsing %s, out of memory. "
770 return (CKR_HOST_MEMORY
);
773 *mech_list
= tmp_list
;
776 * The following will loop mech_count times, as there are
777 * exactly mech_count items in the str_list.
779 while (shead
!= NULL
) {
780 CK_MECHANISM_TYPE cur_mech
;
785 * "name" is a hexadecimal number, preceded by 0x.
787 cur_mech
= strtoul(shead
->name
, NULL
, 16);
789 if ((cur_mech
== 0) &&
790 ((errno
== EINVAL
) || (errno
== ERANGE
))) {
792 return (CKR_MECHANISM_INVALID
);
794 *tmp_list
= (CK_MECHANISM_TYPE
)cur_mech
;
803 * pkcs11_is_dismech is provided a slotid and a mechanism.
804 * If mech is not disabled, then return B_FALSE.
807 pkcs11_is_dismech(CK_SLOT_ID slotid
, CK_MECHANISM_TYPE mech
)
810 boolean_t enabled_pol
;
811 CK_MECHANISM_TYPE_PTR pol_mechs
;
814 /* Find the associated slot and get the mech policy info */
815 (void) pthread_mutex_lock(&slottable
->st_slots
[slotid
]->sl_mutex
);
816 enabled_pol
= slottable
->st_slots
[slotid
]->sl_enabledpol
;
817 pol_mechs
= slottable
->st_slots
[slotid
]->sl_pol_mechs
;
818 pol_count
= slottable
->st_slots
[slotid
]->sl_pol_count
;
819 (void) pthread_mutex_unlock(&slottable
->st_slots
[slotid
]->sl_mutex
);
821 /* Check for policy */
822 if ((!enabled_pol
) && (pol_mechs
== NULL
)) {
825 } else if (pol_mechs
== NULL
) {
827 * We have an empty enabled list, which means no
828 * mechanisms are exempted from this policy: all
834 for (i
= 0; i
< pol_count
; i
++) {
836 * If it matches, return status based on this
837 * being and enabled or a disabled list of mechs.
839 if (pol_mechs
[i
] == mech
) {
840 return (enabled_pol
? B_FALSE
: B_TRUE
);
844 /* mech was not found in list */
845 return (enabled_pol
? B_TRUE
: B_FALSE
);