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

Reply via email to