Ludovic Rousseau wrote:
On Thu, Aug 28, 2008 at 1:02 AM, Huie-Ying Lee <[EMAIL PROTECTED]> wrote:
Douglas E. Engert wrote:
This sounds like an interesting change. But could it be reworked to
allow the use of either the slot_num or the slot_description?
(But not both.) This would then avoid all the #ifdef SUN_SOLARIS
and make the mod more general, and easier to test.
This sounds like a good suggestion. In fact, I was also thinking about
this arrangement prior to submit this patch.
I will go ahead to make the enhancement and resummit the patch.
Good.
Do not change the Makefile.am to add -DSUN_SOLARIS. You should add any
plateform specific flag using "./configure CPPFLAFS=-DSUN_SOLARIS".
But the problem will solve itself since you will rewrite your patch to
avoid all the #ifdef SUN_SOLARIS
Bye
Hello,
Per your sugestion, I have reworked the patch to allow a user to choose
a slot by using either slot_num or slot_description as below:
--- pam_pkcs11.conf ----
pkcs11_module default {
...
pkcs11_module opensc {
module = /usr/lib/opensc-pkcs11.so;
description = "OpenSC PKCS#11 module";
# Which slot to use ?
# You can use "slot_num" or "slot_description", but not both, to specify
# the slot to use. Using "slot_description" is preferred because the
# PKCS#11 specification does not guarantee slot ordering. "slot_num"
should
# only be used with those PKCS11#11 implementations that ensure
guarantee
# slot numbering.
#
# slot_description = "xxxx"
# The slot is specified by the slot description, for example,
# slot_description = "Sun Crypto Softtoken". The default value is
# "none" which means to use the first slot with an available token.
#
# slot_num = a_number
# The slot is specified by the slot number, for example,
slot_num = 1.
# The default value is zero which means to use the first slot
with an
# available token.
#
slot_description = "none";
...
--------------------------
I have completed the source changes and tested it successfully on
Solaris OS. Besides the major slot_description/slot_num changes for the
default implementation, the source changes also include
1. slot_description/slot_num changes are also updated for the NSS
implementation in the src/common/pkcs11_lib.c file. Therefore, the
new scheme will work as well if it is built with "--with-nss=yes".
2. A bug fix in src/common/pam_config.c: in line 259, "slot_nume="
should be "slot_num="
3. A bug fix in src/common/pkcs11_lib.c: in line 290 and 291,
slots[i] should be slots[slot_num]
4. In the original pkcs11_lib.c, all the places in the ORIIGINAL code
that use "slot_label" actually refer to a token label, so their names
are changed to token_label. With the same reason, the function
get_slot_label() is renamed to get_slot_tokenlabel().
5. Some platform specific changes to compile and build On OpenSolaris
OS. These changes are guarded with "ifdef SUN_SOLARIS".
Attached is the source patch, please review it and let me know if you
have any questions or comments.
Thanks,
Huie-Ying
Index: src/pam_pkcs11/pam_pkcs11.c
===================================================================
--- src/pam_pkcs11/pam_pkcs11.c (revision 327)
+++ src/pam_pkcs11/pam_pkcs11.c (working copy)
@@ -83,12 +83,20 @@
msg.msg_style = style;
msg.msg = text;
+#ifdef SUN_SOLARIS
+ rv = pam_get_item(pamh, PAM_CONV, (void **) &conv);
+#else
rv = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
+#endif
if (rv != PAM_SUCCESS)
return rv;
if ((conv == NULL) || (conv->conv == NULL))
return PAM_CRED_INSUFFICIENT;
+#ifdef SUN_SOLARIS
+ rv = conv->conv(1, (struct pam_message **)msgp, &resp, conv->appdata_ptr);
+#else
rv = conv->conv(1, (const struct pam_message **)msgp, &resp,
conv->appdata_ptr);
+#endif
if (rv != PAM_SUCCESS)
return rv;
if ((resp == NULL) || (resp[0].resp == NULL))
@@ -132,7 +140,11 @@
/* use stored password if variable oitem is set */
if ((oitem == PAM_AUTHTOK) || (oitem == PAM_OLDAUTHTOK)) {
/* try to get stored item */
+#ifdef SUN_SOLARIS
+ rv = pam_get_item(pamh, oitem, (void **) &old_pwd);
+#else
rv = pam_get_item(pamh, oitem, (const void **) &old_pwd);
+#endif
if (rv != PAM_SUCCESS)
return rv;
if (old_pwd != NULL) {
@@ -145,12 +157,20 @@
if (text != NULL) {
msg.msg_style = PAM_PROMPT_ECHO_OFF;
msg.msg = text;
+#ifdef SUN_SOLARIS
+ rv = pam_get_item(pamh, PAM_CONV, (void **) &conv);
+#else
rv = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
+#endif
if (rv != PAM_SUCCESS)
return rv;
if ((conv == NULL) || (conv->conv == NULL))
return PAM_CRED_INSUFFICIENT;
+#ifdef SUN_SOLARIS
+ rv = conv->conv(1, (struct pam_message **)msgp, &resp, conv->appdata_ptr);
+#else
rv = conv->conv(1, (const struct pam_message **)msgp, &resp,
conv->appdata_ptr);
+#endif
if (rv != PAM_SUCCESS)
return rv;
if ((resp == NULL) || (resp[0].resp == NULL))
@@ -206,6 +226,12 @@
return PAM_AUTHINFO_UNAVAIL;
}
+ /* Either slot_description or slot_num, but not both, needs to be used */
+ if ((configuration->slot_description != NULL && configuration->slot_num !=
-1) || (configuration->slot_description == NULL && configuration->slot_num ==
-1)) {
+ ERR("Error setting configuration parameters");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
/* fail if we are using a remote server
* local login: DISPLAY=:0
* XDMCP login: DISPLAY=host:0 */
@@ -257,7 +283,11 @@
char *service;
if (configuration->screen_savers) {
DBG("Is it a screen saver?");
+#ifdef SUN_SOLARIS
+ rv = pam_get_item(pamh, PAM_SERVICE, (void **) &service);
+#else
rv = pam_get_item(pamh, PAM_SERVICE, (const void **) &service);
+#endif
for (i=0; configuration->screen_savers[i]; i++) {
if (strcmp(configuration->screen_savers[i], service) == 0) {
is_a_screen_saver = 1;
@@ -269,7 +299,11 @@
pkcs11_pam_fail = PAM_CRED_INSUFFICIENT;
/* look to see if username is already set */
+#ifdef SUN_SOLARIS
+ rv = pam_get_item(pamh, PAM_USER, (void **) &user);
+#else
rv = pam_get_item(pamh, PAM_USER, (const void **) &user);
+#endif
if (user) {
DBG1("explicit username = [%s]", user);
}
@@ -314,8 +348,14 @@
}
/* open pkcs #11 session */
- rv = find_slot_by_number_and_label(ph, configuration->slot_num,
+ if (configuration->slot_description != NULL) {
+ rv = find_slot_by_slotlabel_and_tokenlabel(ph,
+ configuration->slot_description, login_token_name, &slot_num);
+ } else if (configuration->slot_num != -1) {
+ rv = find_slot_by_number_and_label(ph, configuration->slot_num,
login_token_name, &slot_num);
+ }
+
if (rv != 0) {
ERR("no suitable token available");
pam_syslog(pamh, LOG_ERR, "no suitable token available");
@@ -337,8 +377,15 @@
pam_prompt(pamh, PAM_TEXT_INFO, NULL,
_("Please insert your smart card."));
}
- rv = wait_for_token(ph, configuration->slot_num,
+
+ if (configuration->slot_description != NULL) {
+ rv = wait_for_token_by_slotlabel(ph, configuration->slot_description,
+ login_token_name, &slot_num);
+ } else if (configuration->slot_num != -1) {
+ rv = wait_for_token(ph, configuration->slot_num,
login_token_name, &slot_num);
+ }
+
if (rv != 0) {
release_pkcs11_module(ph);
return pkcs11_pam_fail;
@@ -356,7 +403,13 @@
/* check one last time for the smart card before bouncing to the next
* module */
- rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+ if (configuration->slot_description != NULL) {
+ rv = find_slot_by_slotlabel(ph, configuration->slot_description,
+ &slot_num);
+ } else if (configuration->slot_num != -1) {
+ rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+ }
+
if (rv != 0) {
/* user gave us a user id and no smart card go to next module */
release_pkcs11_module(ph);
@@ -366,6 +419,7 @@
} else {
pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Smart card inserted. "));
}
+
rv = open_pkcs11_session(ph, slot_num);
if (rv != 0) {
release_pkcs11_module(ph);
@@ -375,7 +429,7 @@
}
/* get password */
- sprintf(password_prompt, _("Welcome %.32s!"), get_slot_label(ph));
+ sprintf(password_prompt, _("Welcome %.32s!"), get_slot_tokenlabel(ph));
pam_prompt(pamh, PAM_TEXT_INFO, NULL, password_prompt);
if (configuration->use_first_pass) {
rv = pam_get_pwd(pamh, &password, NULL, PAM_AUTHTOK, 0);
@@ -558,7 +612,7 @@
snprintf(env_temp, sizeof(env_temp) - 1,
"PKCS11_LOGIN_TOKEN_NAME=%.*s",
(sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_TOKEN_NAME="),
- get_slot_label(ph));
+ get_slot_tokenlabel(ph));
rv = pam_putenv(pamh, env_temp);
if (rv != PAM_SUCCESS) {
Index: src/pam_pkcs11/pam_config.c
===================================================================
--- src/pam_pkcs11/pam_config.c (revision 327)
+++ src/pam_pkcs11/pam_config.c (working copy)
@@ -45,7 +45,8 @@
"default", /* const char *pkcs11_module; */
CONFDIR "/pkcs11_module.so",/* const char *pkcs11_module_path; */
NULL, /* screen savers */
- 0, /* int slot_num; */
+ NULL, /* slot_description */
+ -1, /* int slot_num; */
0, /* support threads */
/* cert policy; */
{
@@ -145,8 +146,22 @@
scconf_get_str(pkcs11_mblk,"crl_dir",configuration.policy.crl_dir);
configuration.policy.nss_dir = (char *)
scconf_get_str(pkcs11_mblk,"nss_dir",configuration.policy.nss_dir);
+ configuration.slot_description = (char *)
+
scconf_get_str(pkcs11_mblk,"slot_description",configuration.slot_description);
+
configuration.slot_num =
scconf_get_int(pkcs11_mblk,"slot_num",configuration.slot_num);
+
+ if (configuration.slot_description != NULL &&
configuration.slot_num != -1) {
+ DBG1("Can not specify both slot_description and slot_num in
file %s",configuration.config_file);
+ return;
+ }
+
+ if (configuration.slot_description == NULL &&
configuration.slot_num == -1) {
+ DBG1("Neither slot_description nor slot_num found in file
%s",configuration.config_file);
+ return;
+ }
+
configuration.support_threads =
scconf_get_bool(pkcs11_mblk,"support_threads",configuration.support_threads);
policy_list= scconf_find_list(pkcs11_mblk,"cert_policy");
@@ -255,10 +270,17 @@
res=sscanf(argv[i],"pkcs11_module=%255s",configuration.pkcs11_module);
continue;
}
+
+ if (strstr(argv[i],"slot_description=") ) {
+
res=sscanf(argv[i],"slot_description=%255s",&configuration.slot_description);
+ continue;
+ }
+
if (strstr(argv[i],"slot_num=") ) {
- res=sscanf(argv[i],"slot_nume=%d",&configuration.slot_num);
+ res=sscanf(argv[i],"slot_num=%d",&configuration.slot_num);
continue;
}
+
if (strstr(argv[i],"ca_dir=") ) {
res=sscanf(argv[i],"ca_dir=%255s",configuration.policy.ca_dir);
continue;
@@ -308,4 +330,3 @@
}
return &configuration;
}
-
Index: src/pam_pkcs11/pam_config.h
===================================================================
--- src/pam_pkcs11/pam_config.h (revision 327)
+++ src/pam_pkcs11/pam_config.h (working copy)
@@ -38,6 +38,7 @@
char *pkcs11_module;
char *pkcs11_modulepath;
char **screen_savers;
+ char *slot_description;
int slot_num;
int support_threads;
cert_policy policy;
Index: src/tools/pkcs11_listcerts.c
===================================================================
--- src/tools/pkcs11_listcerts.c (revision 327)
+++ src/tools/pkcs11_listcerts.c (working copy)
@@ -53,6 +53,11 @@
return 1;
}
+ if ((configuration->slot_description != NULL && configuration->slot_num !=
-1) || (configuration->slot_description == NULL && configuration->slot_num ==
-1)) {
+ ERR("Error setting configuration parameters");
+ return 1;
+ }
+
/* init openssl */
rv = crypto_init(&configuration->policy);
if (rv != 0) {
@@ -78,7 +83,12 @@
}
/* open pkcs #11 session */
- rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+ if (configuration->slot_description != NULL) {
+ rv = find_slot_by_slotlabel(ph,configuration->slot_description, &slot_num);
+ } else {
+ rv = find_slot_by_number(ph,configuration->slot_num, &slot_num);
+ }
+
if (rv != 0) {
release_pkcs11_module(ph);
DBG("no token available");
Index: src/tools/pkcs11_inspect.c
===================================================================
--- src/tools/pkcs11_inspect.c (revision 327)
+++ src/tools/pkcs11_inspect.c (working copy)
@@ -53,6 +53,11 @@
return 1;
}
+ if ((configuration->slot_description != NULL && configuration->slot_num !=
-1) || (configuration->slot_description == NULL && configuration->slot_num ==
-1)) {
+ ERR("Error setting configuration parameters");
+ return 1;
+ }
+
/* init openssl */
rv = crypto_init(&configuration->policy);
if (rv != 0) {
@@ -79,7 +84,12 @@
}
/* open pkcs #11 session */
- rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+ if (configuration->slot_description != NULL) {
+ rv = find_slot_by_slotlabel(ph, configuration->slot_description,
&slot_num);
+ } else {
+ rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+ }
+
if (rv != 0) {
release_pkcs11_module(ph);
DBG("no token available");
@@ -117,7 +127,7 @@
/* find valid certificates and look for contents */
DBG1("Found '%d' certificate(s)", cert_count);
for (i = 0; i < cert_count; i++) {
- X509 *x509 = get_X509_certificate(certs[i]);
+ X509 *x509 = (X509 *)get_X509_certificate(certs[i]);
if (x509 != NULL) {
DBG1("verifing the certificate #%d", i + 1);
/* verify certificate (date, signature, CRL, ...) */
Index: src/tools/pkcs11_eventmgr.c
===================================================================
--- src/tools/pkcs11_eventmgr.c (revision 327)
+++ src/tools/pkcs11_eventmgr.c (working copy)
@@ -431,6 +431,7 @@
}
}
+#ifndef SUN_SOLARIS
if (daemonize) {
DBG("Going to be daemon...");
if ( daemon(0,debug)<0 ) {
@@ -441,6 +442,7 @@
return 1;
}
}
+#endif
/*
* Wait endlessly for all events in the list of readers
@@ -513,6 +515,7 @@
}
/* put my self into background if flag is set */
+#ifndef SUN_SOLARIS
if (daemonize) {
DBG("Going to be daemon...");
if ( daemon(0,debug)<0 ) {
@@ -522,6 +525,7 @@
return 1;
}
}
+#endif
/* open pkcs11 sesion */
DBG("initialising pkcs #11 module...");
Index: src/tools/pklogin_finder.c
===================================================================
--- src/tools/pklogin_finder.c (revision 327)
+++ src/tools/pklogin_finder.c (working copy)
@@ -55,6 +55,11 @@
return 1;
}
+ if ((configuration->slot_description != NULL && configuration->slot_num !=
-1) || (configuration->slot_description == NULL && configuration->slot_num ==
-1)) {
+ ERR("Error setting configuration parameters");
+ return 1;
+ }
+
/* init openssl */
rv = crypto_init(&configuration->policy);
if (rv != 0) {
@@ -80,7 +85,11 @@
}
/* open pkcs #11 session */
- rv = find_slot_by_number(ph,configuration->slot_num, &slot_num);
+ if (configuration->slot_description != NULL) {
+ rv = find_slot_by_slotlabel(ph,configuration->slot_description, &slot_num);
+ } else {
+ rv = find_slot_by_number(ph,configuration->slot_num, &slot_num);
+ }
if (rv != 0) {
release_pkcs11_module(ph);
DBG("no token available");
@@ -117,7 +126,7 @@
/* find a valid and matching certificates */
DBG1("Found '%d' certificate(s)", cert_count);
for (i = 0; i < cert_count; i++) {
- X509 *x509 = get_X509_certificate(certs[i]);
+ X509 *x509 = (X509 *)get_X509_certificate(certs[i]);
if (x509 != NULL) {
DBG1("verifing the certificate #%d", i + 1);
/* verify certificate (date, signature, CRL, ...) */
Index: src/common/pkcs11_lib.c
===================================================================
--- src/common/pkcs11_lib.c (revision 327)
+++ src/common/pkcs11_lib.c (working copy)
@@ -67,13 +67,76 @@
return 0;
}
+/*
+ * memcmp_pad_max() is a specialized version of memcmp() which compares two
+ * pieces of data up to a maximum length. If the two data match up the
+ * maximum length, they are considered matching. Trailing blanks do not cause
+ * the match to fail if one of the data is shorted.
+ *
+ * Examples of matches:
+ * "one" |
+ * "one " |
+ * ^maximum length
+ *
+ * "Number One | X" (X is beyond maximum length)
+ * "Number One " |
+ * ^maximum length
+ *
+ * Examples of mismatches:
+ * " one"
+ * "one"
+ *
+ * "Number One X|"
+ * "Number One |"
+ * ^maximum length
+ */
+static int
+memcmp_pad_max(void *d1, size_t d1_len, void *d2, size_t d2_len,
+ size_t max_sz)
+{
+ size_t len, extra_len;
+ char *marker;
+
+ /* No point in comparing anything beyond max_sz */
+ if (d1_len > max_sz)
+ d1_len = max_sz;
+ if (d2_len > max_sz)
+ d2_len = max_sz;
+
+ /* Find shorter of the two data. */
+ if (d1_len <= d2_len) {
+ len = d1_len;
+ extra_len = d2_len;
+ marker = d2;
+ } else { /* d1_len > d2_len */
+ len = d2_len;
+ extra_len = d1_len;
+ marker = d1;
+ }
+
+ /* Have a match in the shortest length of data? */
+ if (memcmp(d1, d2, len) != 0)
+ /* CONSTCOND */
+ return (1);
+
+ /* If the rest of longer data is nulls or blanks, call it a match. */
+ while (len < extra_len && marker[len])
+ if (!isspace(marker[len++]))
+ /* CONSTCOND */
+ return (1);
+ return (0);
+}
+
+
#ifdef HAVE_NSS
/*
* Using NSS to find the manage the PKCS #11 modules
*/
#include "nss.h"
+#include "nspr.h"
#include "cert.h"
#include "secmod.h"
+#include "secutil.h"
#include "pk11pub.h"
#include "cert_st.h"
#include "secutil.h"
@@ -85,6 +148,8 @@
#include "cert_vfy.h"
+const char * SECU_Strerror(PRErrorCode errNum);
+
#ifndef PAM_PKCS11_POLL_TIME
#define PAM_PKCS11_POLL_TIME 500 /* ms */
#endif
@@ -287,8 +352,8 @@
/* we're configured for a specific module and token, see if it's present */
slot_num--;
if (slot_num >= 0 && slot_num < module->slotCount && module->slots &&
- module->slots[i] && PK11_IsPresent(module->slots[i])) {
- h->slot = PK11_ReferenceSlot(module->slots[i]);
+ module->slots[slot_num] && PK11_IsPresent(module->slots[slot_num])) {
+ h->slot = PK11_ReferenceSlot(module->slots[slot_num]);
*slotID = PK11_GetSlotID(h->slot);
return 0;
}
@@ -301,34 +366,34 @@
*/
int find_slot_by_number_and_label(pkcs11_handle_t *h,
int wanted_slot_id,
- const char *wanted_slot_label,
+ const char *wanted_token_label,
unsigned int *slot_num)
{
int rv;
- const char *slot_label = NULL;
+ const char *token_label = NULL;
PK11SlotInfo *slot = NULL;
/* we want a specific slot id, or we don't kare about the label */
- if ((wanted_slot_label == NULL) || (wanted_slot_id != 0)) {
+ if ((wanted_token_label == NULL) || (wanted_slot_id != 0)) {
rv = find_slot_by_number(h, wanted_slot_id, slot_num);
/* if we don't care about the label, or we failed, we're done */
- if ((wanted_slot_label == NULL) || (rv != 0)) {
+ if ((wanted_token_label == NULL) || (rv != 0)) {
return rv;
}
/* verify it's the label we want */
- slot_label = PK11_GetTokenName(h->slot);
+ token_label = PK11_GetTokenName(h->slot);
- if ((slot_label != NULL) &&
- (strcmp (wanted_slot_label, slot_label) == 0)) {
+ if ((token_label != NULL) &&
+ (strcmp (wanted_token_label, token_label) == 0)) {
return 0;
}
return -1;
}
/* we want a specific slot by label only */
- slot = PK11_FindSlotByName(wanted_slot_label);
+ slot = PK11_FindSlotByName(wanted_token_label);
if (!slot) {
return -1;
}
@@ -350,7 +415,7 @@
int wait_for_token(pkcs11_handle_t *h,
int wanted_slot_id,
- const char *wanted_slot_label,
+ const char *wanted_token_label,
unsigned int *slot_num)
{
int rv;
@@ -358,7 +423,7 @@
rv = -1;
do {
/* see if the card we're looking for is inserted */
- rv = find_slot_by_number_and_label (h, wanted_slot_id, wanted_slot_label,
+ rv = find_slot_by_number_and_label (h, wanted_slot_id, wanted_token_label,
slot_num);
if (rv != 0) {
PK11SlotInfo *slot;
@@ -385,6 +450,149 @@
return rv;
}
+/*
+ * This function will search the slot list to find a slot based on the slot
+ * label. If the wanted_slot_label is "none", then we will return the first
+ * slot with the token presented.
+ *
+ * This function return 0 if it found a matching slot; otherwise, it returns
+ * -1.
+ */
+int
+find_slot_by_slotlabel(pkcs11_handle_t *h, const char *wanted_slot_label,
+ unsigned int *slotID)
+{
+ SECMODModule *module = h->module;
+ PK11SlotInfo *slot;
+ int rv;
+ int i;
+
+ if (slotID == NULL || wanted_slot_label == NULL ||
+ strlen(wanted_slot_label) == 0 || module == NULL)
+ return (-1);
+
+ if (strcmp(wanted_slot_label, "none") == 0) {
+ rv = find_slot_by_number(h, 0, slotID);
+ return (rv);
+ } else {
+ /* wanted_slot_label is not "none" */
+ for (i = 0; i < module->slotCount; i++) {
+ if (module->slots[i] && PK11_IsPresent(module->slots[i])) {
+ const char *slot_label;
+
+ slot = PK11_ReferenceSlot(module->slots[i]);
+ slot_label = PK11_GetSlotName(slot);
+ if (memcmp_pad_max((void *)slot_label, strlen(slot_label),
+ (void *)wanted_slot_label, strlen(wanted_slot_label), 64) == 0) {
+ h->slot = slot;
+ *slotID = PK11_GetSlotID(slot);
+ return 0;
+ }
+ }
+ }
+ }
+
+ return (-1);
+}
+
+
+int
+find_slot_by_slotlabel_and_tokenlabel(pkcs11_handle_t *h,
+ const char *wanted_slot_label, const char *wanted_token_label,
+ unsigned int *slot_num)
+{
+ SECMODModule *module = h->module;
+ PK11SlotInfo *slot;
+ unsigned long i;
+ int rv;
+
+ if (slot_num == NULL || module == NULL)
+ return (-1);
+
+ if (wanted_token_label == NULL){
+ rv = find_slot_by_slotlabel(h, wanted_slot_label, slot_num);
+ return (rv);
+ }
+
+ /* wanted_token_label != NULL */
+ if (strcmp(wanted_slot_label, "none") == 0) {
+ for (i = 0; i < module->slotCount; i++) {
+ if (module->slots[i] && PK11_IsPresent(module->slots[i])) {
+ const char *token_label;
+ slot = PK11_ReferenceSlot(module->slots[i]);
+ token_label = PK11_GetTokenName(slot);
+ if (memcmp_pad_max((void *) token_label, strlen(token_label),
+ (void *)wanted_token_label, strlen(wanted_token_label), 33) == 0) {
+ h->slot = slot;
+ *slot_num = PK11_GetSlotID(slot);
+ return (0);
+ }
+ }
+ }
+ return (-1);
+ } else {
+ for (i = 0; i < module->slotCount; i++) {
+ if (module->slots[i] && PK11_IsPresent(module->slots[i])) {
+ const char *slot_label;
+ const char *token_label;
+
+ slot = PK11_ReferenceSlot(module->slots[i]);
+ slot_label = PK11_GetSlotName(slot);
+ token_label = PK11_GetTokenName(slot);
+ if ((memcmp_pad_max((void *)slot_label, strlen(slot_label),
+ (void *)wanted_slot_label, strlen(wanted_slot_label), 64) == 0) &&
+ (memcmp_pad_max((void *)token_label, strlen(token_label),
+ (void *)wanted_token_label, strlen(wanted_token_label), 33) == 0))
+ {
+ h->slot = slot;
+ *slot_num = PK11_GetSlotID(slot);
+ return (0);
+ }
+ }
+ }
+ return (-1);
+ }
+}
+
+int wait_for_token_by_slotlabel(pkcs11_handle_t *h,
+ const char *wanted_slot_label,
+ const char *wanted_token_label,
+ unsigned int *slot_num)
+{
+ int rv;
+
+ rv = -1;
+ do {
+ /* see if the card we're looking for is inserted */
+ rv = find_slot_by_slotlabel_and_tokenlabel (h, wanted_slot_label,
+ wanted_token_label, slot_num);
+
+ if (rv != 0) {
+ PK11SlotInfo *slot;
+ PRIntervalTime slot_poll_interval; /* only for legacy hardware */
+
+ /* if the card is not inserted, then block until something happens */
+ slot_poll_interval = PR_MillisecondsToInterval(PAM_PKCS11_POLL_TIME);
+ slot = SECMOD_WaitForAnyTokenEvent(h->module, 0 /* flags */,
+ slot_poll_interval);
+
+ /* unexpected error */
+ if (slot == NULL) {
+ break;
+ }
+
+ /* something happened, continue loop and check if the card
+ * we're looking for is inserted
+ */
+ PK11_FreeSlot(slot);
+ continue;
+ }
+ } while (rv != 0);
+
+ return rv;
+}
+
+
void release_pkcs11_module(pkcs11_handle_t *h)
{
SECStatus rv;
@@ -470,7 +678,7 @@
return 0;
}
-const char *get_slot_label(pkcs11_handle_t *h)
+const char *get_slot_tokenlabel(pkcs11_handle_t *h)
{
if (!h->slot) {
return NULL;
@@ -613,7 +821,6 @@
return (rv == SECSuccess) ? 0 : -1;
}
-#include "nspr.h"
struct tuple_str {
PRErrorCode errNum;
@@ -708,7 +915,8 @@
typedef struct {
CK_SLOT_ID id;
CK_BBOOL token_present;
- CK_UTF8CHAR label[33];
+ CK_UTF8CHAR label[33]; /* token label */
+ CK_UTF8CHAR slotDescription[64];
} slot_t;
struct pkcs11_handle_str {
@@ -758,7 +966,11 @@
DBG3("module permissions: uid = %d, gid = %d, mode = %o",
module_stat.st_uid, module_stat.st_gid, module_stat.st_mode & 0777);
if (module_stat.st_mode & S_IWGRP || module_stat.st_mode & S_IWOTH
+#ifdef SUN_SOLARIS
+ || module_stat.st_uid != 0) {
+#else
|| module_stat.st_uid != 0 || module_stat.st_gid != 0) {
+#endif
set_error("the pkcs #11 module MUST be owned by root and MUST NOT "
"be writeable by the group or others");
free(h);
@@ -807,6 +1019,9 @@
set_error("C_GetSlotInfo() failed: 0x%08lX", rv);
return -1;
}
+
+ (void) memcpy(h->slots[i].slotDescription, sinfo.slotDescription, 64);
+
DBG1("- description: %.64s", sinfo.slotDescription);
DBG1("- manufacturer: %.32s", sinfo.manufacturerID);
DBG1("- flags: %04lx", sinfo.flags);
@@ -945,27 +1160,27 @@
int find_slot_by_number_and_label(pkcs11_handle_t *h,
int wanted_slot_id,
- const char *wanted_slot_label,
+ const char *wanted_token_label,
unsigned int *slot_num)
{
unsigned int slot_index;
int rv;
- const char *slot_label = NULL;
+ const char *token_label = NULL;
/* we want a specific slot id, or we don't care about the label */
- if ((wanted_slot_label == NULL) || (wanted_slot_id != 0)) {
+ if ((wanted_token_label == NULL) || (wanted_slot_id != 0)) {
rv = find_slot_by_number(h, wanted_slot_id, slot_num);
/* if we don't care about the label, or we failed, we're done */
- if ((wanted_slot_label == NULL) || (rv != 0)) {
+ if ((wanted_token_label == NULL) || (rv != 0)) {
return rv;
}
/* verify it's the label we want */
- slot_label = h->slots[*slot_num].label;
+ token_label = h->slots[*slot_num].label;
- if ((slot_label != NULL) &&
- (strcmp (wanted_slot_label, slot_label) == 0)) {
+ if ((token_label != NULL) &&
+ (strcmp (wanted_token_label, token_label) == 0)) {
return 0;
}
return -1;
@@ -974,9 +1189,9 @@
/* look up the slot by it's label from the list */
for (slot_index = 0; slot_index < h->slot_count; slot_index++) {
if (h->slots[slot_index].token_present) {
- slot_label = h->slots[slot_index].label;
- if ((slot_label != NULL) &&
- (strcmp (wanted_slot_label, slot_label) == 0)) {
+ token_label = h->slots[slot_index].label;
+ if ((token_label != NULL) &&
+ (strcmp (wanted_token_label, token_label) == 0)) {
*slot_num = slot_index;
return 0;
}
@@ -985,9 +1200,121 @@
return -1;
}
+
+/*
+ * This function will search the slot list to find a slot based on the slot
+ * label. If the wanted_slot_label is "none", then we will return the first
+ * slot with the token presented.
+ *
+ * This function return 0 if it found a matching slot; otherwise, it returns
+ * -1.
+ */
+int
+find_slot_by_slotlabel(pkcs11_handle_t *h, const char *wanted_slot_label,
+ unsigned int *slot_num)
+{
+ unsigned long index;
+ size_t len;
+
+ if (slot_num == NULL || wanted_slot_label == NULL ||
+ strlen(wanted_slot_label) == 0)
+ return (-1);
+
+ if (strcmp(wanted_slot_label, "none") == 0) {
+ for (index = 0; index < h->slot_count; index++) {
+ if (h->slots[index].token_present) {
+ *slot_num = index;
+ return (0);
+ }
+ }
+ } else {
+ /* Look up the slot by it's slotDescription */
+ len = strlen(wanted_slot_label);
+ for (index = 0; index < h->slot_count; index++) {
+ if (memcmp_pad_max(h->slots[index].slotDescription, 64,
+ (void *)wanted_slot_label, len, 64) == 0) {
+ *slot_num = index;
+ return (0);
+ }
+ }
+ }
+
+ return (-1);
+}
+
+
+int
+find_slot_by_slotlabel_and_tokenlabel(pkcs11_handle_t *h,
+ const char *wanted_slot_label, const char *wanted_token_label,
+ unsigned int *slot_num)
+{
+ unsigned long i;
+ int rv;
+
+ if (slot_num == NULL)
+ return (-1);
+
+ if (wanted_token_label == NULL) {
+ rv = find_slot_by_slotlabel(h, wanted_slot_label, slot_num);
+ return (rv);
+ }
+
+ /* wanted_token_label != NULL */
+ if (strcmp(wanted_slot_label, "none") == 0) {
+ for (i= 0; i < h->slot_count; i++) {
+ if (h->slots[i].token_present &&
+ strcmp(wanted_token_label, h->slots[i].label) == 0) {
+ *slot_num = i;
+ return (0);
+ }
+ }
+ return (-1);
+ } else {
+ for (i = 0; i < h->slot_count; i++) {
+ if (h->slots[i].token_present) {
+ const char *slot_label = h->slots[i].slotDescription;
+ const char *token_label = h->slots[i].label;
+
+ if ((memcmp_pad_max((void *)slot_label, strlen(slot_label),
+ (void *)wanted_slot_label, strlen(wanted_slot_label), 64) == 0) &&
+ (memcmp_pad_max((void *)token_label, strlen(token_label),
+ (void *)wanted_token_label, strlen(wanted_token_label), 33) == 0))
+ {
+ *slot_num = i;
+ return (0);
+ }
+ }
+ }
+ return (-1);
+ }
+}
+
+int wait_for_token_by_slotlabel(pkcs11_handle_t *h,
+ const char *wanted_slot_label,
+ const char *wanted_token_label,
+ unsigned int *slot_num)
+{
+ int rv;
+
+ rv = -1;
+ do {
+ /* see if the card we're looking for is inserted */
+ rv = find_slot_by_slotlabel_and_tokenlabel (h, wanted_slot_label,
+ wanted_token_label, slot_num);
+ if (rv != 0) {
+ /* could call C_WaitForSlotEvent, for now just poll */
+ sleep(10);
+ refresh_slots(h);
+ continue;
+ }
+ } while (rv != 0);
+
+ return rv;
+}
+
int wait_for_token(pkcs11_handle_t *h,
int wanted_slot_id,
- const char *wanted_slot_label,
+ const char *wanted_token_label,
unsigned int *slot_num)
{
int rv;
@@ -995,7 +1322,7 @@
rv = -1;
do {
/* see if the card we're looking for is inserted */
- rv = find_slot_by_number_and_label (h, wanted_slot_id, wanted_slot_label,
+ rv = find_slot_by_number_and_label (h, wanted_slot_id, wanted_token_label,
slot_num);
if (rv != 0) {
/* could call C_WaitForSlotEvent, for now just poll */
@@ -1179,7 +1506,12 @@
/* Pass 3: store certificate */
/* convert to X509 data structure */
+#ifdef SUN_SOLARIS
+ x509 = d2i_X509(NULL, (const uchar_t **)&cert_template[3].pValue,
cert_template[3].ulValueLen);
+#else
x509 = d2i_X509(NULL, (CK_BYTE **)&cert_template[3].pValue,
cert_template[3].ulValueLen);
+#endif
+
if (x509 == NULL) {
free(id_value);
free(cert_value);
@@ -1306,7 +1638,7 @@
return -1;
}
-const char *get_slot_label(pkcs11_handle_t *h)
+const char *get_slot_tokenlabel(pkcs11_handle_t *h)
{
return h->slots[h->current_slot].label;
}
Index: src/common/pkcs11_lib.h
===================================================================
--- src/common/pkcs11_lib.h (revision 327)
+++ src/common/pkcs11_lib.h (working copy)
@@ -36,11 +36,22 @@
PKCS11_EXTERN int find_slot_by_number_and_label(pkcs11_handle_t *h,
int slot_num, const char *slot_label,
unsigned int *slot);
-PKCS11_EXTERN const char *get_slot_label(pkcs11_handle_t *h);
+PKCS11_EXTERN const char *get_slot_tokenlabel(pkcs11_handle_t *h);
PKCS11_EXTERN int wait_for_token(pkcs11_handle_t *h,
int wanted_slot_num,
- const char *wanted_slot_label,
+ const char *wanted_token_label,
unsigned int *slot);
+PKCS11_EXTERN int find_slot_by_slotlabel(pkcs11_handle_t *h,
+ const char *wanted_slot_label,
+ unsigned int *slot);
+PKCS11_EXTERN int find_slot_by_slotlabel_and_tokenlabel(pkcs11_handle_t *h,
+ const char *wanted_slot_label,
+ const char *wanted_token_label,
+ unsigned int *slot);
+PKCS11_EXTERN int wait_for_token_by_slotlabel(pkcs11_handle_t *h,
+ const char *wanted_slot_label,
+ const char *wanted_token_label,
+ unsigned int *slot);
PKCS11_EXTERN const X509 *get_X509_certificate(cert_object_t *cert);
PKCS11_EXTERN void release_pkcs11_module(pkcs11_handle_t *h);
PKCS11_EXTERN int open_pkcs11_session(pkcs11_handle_t *h, unsigned int slot);
Index: etc/pam_pkcs11.conf.example
===================================================================
--- etc/pam_pkcs11.conf.example (revision 327)
+++ etc/pam_pkcs11.conf.example (working copy)
@@ -29,11 +29,26 @@
pkcs11_module opensc {
module = /usr/lib/opensc-pkcs11.so;
description = "OpenSC PKCS#11 module";
- # Slot-number to use. One for the first, two for the second and so
- # on. The default value is zero which means to use the first slot
- # with an available token.
- slot_num = 0;
+ # Which slot to use ?
+ # You can use "slot_num" or "slot_description", but not both, to specify
+ # the slot to use. Using "slot_description" is preferred because the
+ # PKCS#11 specification does not guarantee slot ordering. "slot_num" should
+ # only be used with those PKCS11#11 implementations that ensure guarantee
+ # slot numbering.
+ #
+ # slot_description = "xxxx"
+ # The slot is specified by the slot description, for example,
+ # slot_description = "Sun Crypto Softtoken". The default value is
+ # "none" which means to use the first slot with an available token.
+ #
+ # slot_num = a_number
+ # The slot is specified by the slot number, for example, slot_num = 1.
+ # The default value is zero which means to use the first slot with an
+ # available token.
+ #
+ slot_description = "none";
+
# Where are CA certificates stored?
# You can setup this value to:
# 1- A directory with openssl hash-links to all certificates
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel