components/pam_pkcs11/patches/pam_pkcs11.patch
changeset 291 b454e61af367
child 5682 94c0ca64c022
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/pam_pkcs11/patches/pam_pkcs11.patch	Wed Jun 08 18:37:56 2011 -0700
@@ -0,0 +1,1574 @@
+*** pam_pkcs11-0.6.0-ORIG/configure.in	Mon Jun 11 05:17:38 2007
+--- pam_pkcs11-WS/configure.in	Mon Sep 28 16:06:48 2009
+***************
+*** 237,243 ****
+  AC_FUNC_REALLOC
+  AC_FUNC_STAT
+  AC_FUNC_VPRINTF
+! AC_CHECK_FUNCS([memset strdup strerror])
+  
+  
+  AC_CONFIG_FILES([ 
+--- 237,243 ----
+  AC_FUNC_REALLOC
+  AC_FUNC_STAT
+  AC_FUNC_VPRINTF
+! AC_CHECK_FUNCS([memset strdup strerror daemon])
+  
+  
+  AC_CONFIG_FILES([ 
+*** pam_pkcs11-0.6.0-ORIG/po/Makefile.in.in	Tue May 22 00:54:56 2007
+--- pam_pkcs11-WS/po/Makefile.in.in	Mon Sep 28 16:06:48 2009
+***************
+*** 46,61 ****
+  GMSGFMT_ = @GMSGFMT@
+  GMSGFMT_no = @GMSGFMT@
+  GMSGFMT_yes = @GMSGFMT_015@
+! GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
+  MSGFMT_ = @MSGFMT@
+  MSGFMT_no = @MSGFMT@
+  MSGFMT_yes = @MSGFMT_015@
+  MSGFMT = $(MSGFMT_$(USE_MSGCTXT))
+! XGETTEXT_ = @XGETTEXT@
+  XGETTEXT_no = @XGETTEXT@
+  XGETTEXT_yes = @XGETTEXT_015@
+  XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
+! MSGMERGE = msgmerge
+  MSGMERGE_UPDATE = @MSGMERGE@ --update
+  MSGINIT = msginit
+  MSGCONV = msgconv
+--- 46,61 ----
+  GMSGFMT_ = @GMSGFMT@
+  GMSGFMT_no = @GMSGFMT@
+  GMSGFMT_yes = @GMSGFMT_015@
+! GMSGFMT = msgfmt
+  MSGFMT_ = @MSGFMT@
+  MSGFMT_no = @MSGFMT@
+  MSGFMT_yes = @MSGFMT_015@
+  MSGFMT = $(MSGFMT_$(USE_MSGCTXT))
+! XGETTEXT_ = /bin/xgettext
+  XGETTEXT_no = @XGETTEXT@
+  XGETTEXT_yes = @XGETTEXT_015@
+  XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
+! MSGMERGE = /usr/lib/intltool/gettext-tools/msgmerge
+  MSGMERGE_UPDATE = @MSGMERGE@ --update
+  MSGINIT = msginit
+  MSGCONV = msgconv
+***************
+*** 87,94 ****
+  .po.gmo:
+  	@lang=`echo $* | sed -e 's,.*/,,'`; \
+  	test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+! 	echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \
+! 	cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
+  
+  .sin.sed:
+  	sed -e '/^#/d' $< > t-$@
+--- 87,94 ----
+  .po.gmo:
+  	@lang=`echo $* | sed -e 's,.*/,,'`; \
+  	test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+! 	echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -o $${lang}.gmo $${lang}.po"; \
+! 	cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
+  
+  .sin.sed:
+  	sed -e '/^#/d' $< > t-$@
+***************
+*** 135,145 ****
+  	else \
+  	  msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
+  	fi; \
+! 	$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
+! 	  --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \
+! 	  --files-from=$(srcdir)/POTFILES.in \
+! 	  --copyright-holder='$(COPYRIGHT_HOLDER)' \
+! 	  --msgid-bugs-address="$$msgid_bugs_address"
+  	test ! -f $(DOMAIN).po || { \
+  	  if test -f $(srcdir)/$(DOMAIN).pot; then \
+  	    sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
+--- 135,142 ----
+  	else \
+  	  msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
+  	fi; \
+! 	$(XGETTEXT) -ns -c TRANSLATORS: -m "" -d $(DOMAIN) \
+! 	  ../src/pam_pkcs11/pam_pkcs11.c
+  	test ! -f $(DOMAIN).po || { \
+  	  if test -f $(srcdir)/$(DOMAIN).pot; then \
+  	    sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
+*** pam_pkcs11-0.6.0-ORIG/src/common/pkcs11_lib.h	Mon May 21 02:46:19 2007
+--- pam_pkcs11-WS/src/common/pkcs11_lib.h	Mon Sep 28 16:06:48 2009
+***************
+*** 36,46 ****
+  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 int wait_for_token(pkcs11_handle_t *h,
+                                   int wanted_slot_num, 
+                                   const char *wanted_slot_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);
+--- 36,57 ----
+  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_tokenlabel(pkcs11_handle_t *h);
+  PKCS11_EXTERN int wait_for_token(pkcs11_handle_t *h,
+                                   int wanted_slot_num, 
++                                  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);
+*** pam_pkcs11-0.6.0-ORIG/src/common/pkcs11_lib.c	Wed Jun  6 02:33:10 2007
+--- pam_pkcs11-WS/src/common/pkcs11_lib.c	Mon Sep 28 16:06:48 2009
+***************
+*** 67,77 ****
+--- 67,138 ----
+    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 "pk11pub.h"
+***************
+*** 287,294 ****
+    /* 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]);
+      *slotID = PK11_GetSlotID(h->slot);
+      return 0;
+    }
+--- 348,355 ----
+    /* 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[slot_num] && PK11_IsPresent(module->slots[slot_num])) {
+!     h->slot = PK11_ReferenceSlot(module->slots[slot_num]);
+      *slotID = PK11_GetSlotID(h->slot);
+      return 0;
+    }
+***************
+*** 301,327 ****
+   */
+  int find_slot_by_number_and_label(pkcs11_handle_t *h, 
+  				  int wanted_slot_id,
+! 				  const char *wanted_slot_label,
+                                    unsigned int *slot_num)
+  {
+    int rv;
+!   const char *slot_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)) {
+      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)) {
+        return rv;
+      }
+  
+      /* verify it's the label we want */
+!     slot_label = PK11_GetTokenName(h->slot);
+  
+!     if ((slot_label != NULL) && 
+!         (strcmp (wanted_slot_label, slot_label) == 0)) {
+        return 0;
+      }
+      return -1;
+--- 362,388 ----
+   */
+  int find_slot_by_number_and_label(pkcs11_handle_t *h, 
+  				  int wanted_slot_id,
+! 				  const char *wanted_token_label,
+                                    unsigned int *slot_num)
+  {
+    int rv;
+!   const char *token_label = NULL;
+    PK11SlotInfo *slot = NULL;
+  
+    /* we want a specific slot id, or we don't kare about the label */
+!   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_token_label == NULL) || (rv != 0)) {
+        return rv;
+      }
+  
+      /* verify it's the label we want */
+!     token_label = PK11_GetTokenName(h->slot);
+  
+!     if ((token_label != NULL) && 
+!         (strcmp (wanted_token_label, token_label) == 0)) {
+        return 0;
+      }
+      return -1;
+***************
+*** 328,334 ****
+    }
+  
+    /* we want a specific slot by label only */
+!   slot = PK11_FindSlotByName(wanted_slot_label);
+    if (!slot) {
+      return -1;
+    }
+--- 389,395 ----
+    }
+  
+    /* we want a specific slot by label only */
+!   slot = PK11_FindSlotByName(wanted_token_label);
+    if (!slot) {
+      return -1;
+    }
+***************
+*** 350,356 ****
+  
+  int wait_for_token(pkcs11_handle_t *h, 
+                     int wanted_slot_id,
+!                    const char *wanted_slot_label,
+                     unsigned int *slot_num)
+  {
+    int rv;
+--- 411,417 ----
+  
+  int wait_for_token(pkcs11_handle_t *h, 
+                     int wanted_slot_id,
+!                    const char *wanted_token_label,
+                     unsigned int *slot_num)
+  {
+    int rv;
+***************
+*** 358,364 ****
+    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,
+                                          slot_num);
+      if (rv !=  0) {
+        PK11SlotInfo *slot;
+--- 419,425 ----
+    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_token_label,
+                                          slot_num);
+      if (rv !=  0) {
+        PK11SlotInfo *slot;
+***************
+*** 385,390 ****
+--- 446,592 ----
+    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,476 ****
+    return 0;
+  }
+  
+! const char *get_slot_label(pkcs11_handle_t *h)
+  {
+    if (!h->slot) {
+      return NULL;
+--- 672,678 ----
+    return 0;
+  }
+  
+! const char *get_slot_tokenlabel(pkcs11_handle_t *h)
+  {
+    if (!h->slot) {
+      return NULL;
+***************
+*** 613,619 ****
+    return (rv == SECSuccess) ? 0 : -1;
+  }
+  
+- #include "nspr.h"
+  
+  struct tuple_str {
+      PRErrorCode	 errNum;
+--- 815,820 ----
+***************
+*** 708,714 ****
+  typedef struct {
+    CK_SLOT_ID id;
+    CK_BBOOL token_present;
+!   CK_UTF8CHAR label[33];
+  } slot_t;
+  
+  struct pkcs11_handle_str {
+--- 909,916 ----
+  typedef struct {
+    CK_SLOT_ID id;
+    CK_BBOOL token_present;
+!   CK_UTF8CHAR label[33]; /* token label */
+!   CK_UTF8CHAR slotDescription[64];
+  } slot_t;
+  
+  struct pkcs11_handle_str {
+***************
+*** 758,764 ****
+    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
+!       || module_stat.st_uid != 0 || module_stat.st_gid != 0) {
+      set_error("the pkcs #11 module MUST be owned by root and MUST NOT "
+                "be writeable by the group or others");
+      free(h);
+--- 960,966 ----
+    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
+!       || module_stat.st_uid != 0) {
+      set_error("the pkcs #11 module MUST be owned by root and MUST NOT "
+                "be writeable by the group or others");
+      free(h);
+***************
+*** 807,812 ****
+--- 1009,1018 ----
+        set_error("C_GetSlotInfo() failed: %x", rv);
+        return -1;
+      }
++ 
++     (void) memcpy(h->slots[i].slotDescription, sinfo.slotDescription,
++ 		sizeof(h->slots[i].slotDescription));
++ 
+      DBG1("- description: %.64s", sinfo.slotDescription);
+      DBG1("- manufacturer: %.32s", sinfo.manufacturerID);
+      DBG1("- flags: %04lx", sinfo.flags);
+***************
+*** 945,971 ****
+  	
+  int find_slot_by_number_and_label(pkcs11_handle_t *h, 
+  				  int wanted_slot_id,
+! 				  const char *wanted_slot_label,
+                                    unsigned int *slot_num)
+  {
+    unsigned int slot_index;
+    int rv;
+!   const char *slot_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)) {
+      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)) {
+        return rv;
+      }
+  
+      /* verify it's the label we want */
+!     slot_label = h->slots[*slot_num].label;
+  
+!     if ((slot_label != NULL) && 
+!         (strcmp (wanted_slot_label, slot_label) == 0)) {
+        return 0;
+      }
+      return -1;
+--- 1151,1177 ----
+  	
+  int find_slot_by_number_and_label(pkcs11_handle_t *h, 
+  				  int wanted_slot_id,
+! 				  const char *wanted_token_label,
+                                    unsigned int *slot_num)
+  {
+    unsigned int slot_index;
+    int rv;
+!   const char *token_label = NULL;
+  
+    /* we want a specific slot id, or we don't care about the label */
+!   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_token_label == NULL) || (rv != 0)) {
+        return rv;
+      }
+  
+      /* verify it's the label we want */
+!     token_label = h->slots[*slot_num].label;
+  
+!     if ((token_label != NULL) && 
+!         (strcmp (wanted_token_label, token_label) == 0)) {
+        return 0;
+      }
+      return -1;
+***************
+*** 974,982 ****
+    /* 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)) {
+          *slot_num = slot_index;
+          return 0;
+        }
+--- 1180,1188 ----
+    /* 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) {
+!       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,993 ****
+    return -1;
+  }
+  
+  int wait_for_token(pkcs11_handle_t *h, 
+                     int wanted_slot_id,
+!                    const char *wanted_slot_label,
+                     unsigned int *slot_num)
+  {
+    int rv;
+--- 1191,1310 ----
+    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_token_label,
+                     unsigned int *slot_num)
+  {
+    int rv;
+***************
+*** 995,1001 ****
+    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,
+                                          slot_num);
+      if (rv !=  0) {
+        /* could call C_WaitForSlotEvent, for now just poll */
+--- 1312,1318 ----
+    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_token_label,
+                                          slot_num);
+      if (rv !=  0) {
+        /* could call C_WaitForSlotEvent, for now just poll */
+***************
+*** 1306,1312 ****
+    return -1;
+  }
+  
+! const char *get_slot_label(pkcs11_handle_t *h)
+  {
+    return h->slots[h->current_slot].label;
+  }
+--- 1623,1629 ----
+    return -1;
+  }
+  
+! const char *get_slot_tokenlabel(pkcs11_handle_t *h)
+  {
+    return h->slots[h->current_slot].label;
+  }
+*** pam_pkcs11-0.6.0-ORIG/src/pam_pkcs11/Makefile.in	Wed Jun  6 02:23:27 2007
+--- pam_pkcs11-WS/src/pam_pkcs11/Makefile.in	Mon Sep 28 16:06:48 2009
+***************
+*** 234,241 ****
+  top_builddir = @top_builddir@
+  top_srcdir = @top_srcdir@
+  MAINTAINERCLEANFILES = Makefile.in
+! AM_CFLAGS = -Wall -fno-strict-aliasing $(CRYPTO_CFLAGS)
+! AM_CPPFLAGS = -Wall -fno-strict-aliasing $(CRYPTO_CFLAGS)
+  lib_LTLIBRARIES = pam_pkcs11.la
+  pam_pkcs11_la_SOURCES = pam_pkcs11.c  \
+  			mapper_mgr.c mapper_mgr.h \
+--- 234,241 ----
+  top_builddir = @top_builddir@
+  top_srcdir = @top_srcdir@
+  MAINTAINERCLEANFILES = Makefile.in
+! AM_CFLAGS = $(CRYPTO_CFLAGS)
+! AM_CPPFLAGS = $(CRYPTO_CFLAGS)
+  lib_LTLIBRARIES = pam_pkcs11.la
+  pam_pkcs11_la_SOURCES = pam_pkcs11.c  \
+  			mapper_mgr.c mapper_mgr.h \
+*** pam_pkcs11-0.6.0-ORIG/src/pam_pkcs11/pam_config.h	Wed Jun  6 02:55:02 2007
+--- pam_pkcs11-WS/src/pam_pkcs11/pam_config.h	Mon Sep 28 16:06:48 2009
+***************
+*** 13,19 ****
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   * Lesser General Public License for more details.
+   *
+!  * $Id: pam_config.h 270 2007-05-21 08:13:00Z ludovic.rousseau $
+   */
+  
+  /*
+--- 13,19 ----
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   * Lesser General Public License for more details.
+   *
+!  * $Id: pam_config.h 341 2008-10-14 07:36:46Z ludovic.rousseau $
+   */
+  
+  /*
+***************
+*** 38,46 ****
+--- 38,48 ----
+  	char *pkcs11_module;
+  	char *pkcs11_modulepath;
+  	char **screen_savers;
++ 	char *slot_description;
+  	int slot_num;
+  	int support_threads;
+  	cert_policy policy;
++ 	char *token_type;
+  	char *username; /* provided user name */
+  };
+  
+*** pam_pkcs11-0.6.0-ORIG/src/pam_pkcs11/pam_pkcs11.c	Tue May 22 01:28:33 2007
+--- pam_pkcs11-WS/src/pam_pkcs11/pam_pkcs11.c	Mon Nov  2 15:39:57 2009
+***************
+*** 12,18 ****
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   * Lesser General Public License for more details.
+   *
+!  * $Id: pam_pkcs11.c 281 2007-05-22 08:28:40Z ludovic.rousseau $
+   */
+  
+  /* We have to make this definitions before we include the pam header files! */
+--- 12,18 ----
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   * Lesser General Public License for more details.
+   *
+!  * $Id: pam_pkcs11.c 341 2008-10-14 07:36:46Z ludovic.rousseau $
+   */
+  
+  /* We have to make this definitions before we include the pam header files! */
+***************
+*** 59,65 ****
+  /*
+  * comodity function that returns 1 on null, empty o spaced string
+  */
+! int is_spaced_str(const char *str) {
+  	char *pt=(char *)str;
+  	if(!str) return 1;
+  	if (!strcmp(str,"")) return 1;
+--- 59,65 ----
+  /*
+  * comodity function that returns 1 on null, empty o spaced string
+  */
+! static int is_spaced_str(const char *str) {
+  	char *pt=(char *)str;
+  	if(!str) return 1;
+  	if (!strcmp(str,"")) return 1;
+***************
+*** 91,103 ****
+    rv = conv->conv(1, (const struct pam_message **)msgp, &resp, conv->appdata_ptr);
+    if (rv != PAM_SUCCESS)
+      return rv;
+!   if ((resp == NULL) || (resp[0].resp == NULL))
+      return !response ? PAM_SUCCESS : PAM_CRED_INSUFFICIENT;
+    if (response) {
+       *response = strdup(resp[0].resp);
+    }
+    /* overwrite memory and release it */
+    memset(resp[0].resp, 0, strlen(resp[0].resp));
+    free(&resp[0]);
+    return PAM_SUCCESS;
+  }
+--- 91,106 ----
+    rv = conv->conv(1, (const struct pam_message **)msgp, &resp, conv->appdata_ptr);
+    if (rv != PAM_SUCCESS)
+      return rv;
+!   if ((resp == NULL) || (resp[0].resp == NULL)) {
+!     free(&resp[0]);
+      return !response ? PAM_SUCCESS : PAM_CRED_INSUFFICIENT;
++   }
+    if (response) {
+       *response = strdup(resp[0].resp);
+    }
+    /* overwrite memory and release it */
+    memset(resp[0].resp, 0, strlen(resp[0].resp));
++   free(resp[0].resp);
+    free(&resp[0]);
+    return PAM_SUCCESS;
+  }
+***************
+*** 206,211 ****
+--- 209,220 ----
+  	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 */
+***************
+*** 274,281 ****
+  	    DBG1("explicit username = [%s]", user);
+  	} 
+    } else {
+!         pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+!                    _("Please insert your smart card or enter your username."));
+  	/* get user name */
+  	rv = pam_get_user(pamh, &user, NULL);
+  
+--- 283,292 ----
+  	    DBG1("explicit username = [%s]", user);
+  	} 
+    } else {
+! 	sprintf(password_prompt,
+! 		_("Please insert your %s or enter your username."),
+! 		_(configuration->token_type));
+! 	pam_prompt(pamh, PAM_TEXT_INFO, NULL, password_prompt);
+  	/* get user name */
+  	rv = pam_get_user(pamh, &user, NULL);
+  
+***************
+*** 314,321 ****
+    }
+  
+    /* open pkcs #11 session */
+!   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");
+--- 325,338 ----
+    }
+  
+    /* open pkcs #11 session */
+!   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,344 ****
+          pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+                   _("Please insert your smart card."));
+        }
+!       rv = wait_for_token(ph, configuration->slot_num,
+                            login_token_name, &slot_num);
+        if (rv != 0) {
+          release_pkcs11_module(ph);
+          return pkcs11_pam_fail;
+--- 354,368 ----
+          pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+                   _("Please insert your smart card."));
+        }
+! 
+!       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;
+***************
+*** 350,362 ****
+      } else {
+        /* we haven't prompted for the user yet, get the user and see if
+         * the smart card has been inserted in the mean time */
+!       pam_prompt(pamh, PAM_TEXT_INFO, NULL, 
+!                  _("Please insert your smart card or enter your username."));
+        rv = pam_get_user(pamh, &user, NULL);
+  
+        /* 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 (rv != 0) {
+          /* user gave us a user id and no smart card go to next module */
+          release_pkcs11_module(ph);
+--- 374,394 ----
+      } else {
+        /* we haven't prompted for the user yet, get the user and see if
+         * the smart card has been inserted in the mean time */
+!       sprintf(password_prompt,
+! 	  	_("Please insert your %s or enter your username."),
+! 		_(configuration->token_type));
+!       pam_prompt(pamh, PAM_TEXT_INFO, NULL, password_prompt);
+        rv = pam_get_user(pamh, &user, NULL);
+  
+        /* check one last time for the smart card before bouncing to the next
+         * module */
+!       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);
+***************
+*** 364,370 ****
+        }
+      }
+    } else {
+!       pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Smart card inserted. "));
+    }
+    rv = open_pkcs11_session(ph, slot_num);
+    if (rv != 0) {
+--- 396,404 ----
+        }
+      }
+    } else {
+!       sprintf(password_prompt, _("Found the %s."),
+!          _(configuration->token_type));
+!       pam_prompt(pamh, PAM_TEXT_INFO, NULL, password_prompt);
+    }
+    rv = open_pkcs11_session(ph, slot_num);
+    if (rv != 0) {
+***************
+*** 375,390 ****
+    }
+  
+    /* get password */
+!   sprintf(password_prompt, _("Welcome %.32s!"), get_slot_label(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);
+    } else if (configuration->try_first_pass) {
+!     rv = pam_get_pwd(pamh, &password, _("Smart card password: "), PAM_AUTHTOK,
+        PAM_AUTHTOK);
+    } else {
+!     rv = pam_get_pwd(pamh, &password, _("Smart card password: "), 0,
+!       PAM_AUTHTOK);
+    }
+    if (rv != PAM_SUCCESS) {
+      release_pkcs11_module(ph);
+--- 409,424 ----
+    }
+  
+    /* get password */
+!   sprintf(password_prompt, _("Welcome %.32s!"), get_slot_tokenlabel(ph));
+    pam_prompt(pamh, PAM_TEXT_INFO, NULL, password_prompt);
++   sprintf(password_prompt, _("%s PIN: "), _(configuration->token_type));
+    if (configuration->use_first_pass) {
+      rv = pam_get_pwd(pamh, &password, NULL, PAM_AUTHTOK, 0);
+    } else if (configuration->try_first_pass) {
+!     rv = pam_get_pwd(pamh, &password, password_prompt, PAM_AUTHTOK,
+        PAM_AUTHTOK);
+    } else {
+!     rv = pam_get_pwd(pamh, &password, password_prompt, 0, PAM_AUTHTOK);
+    }
+    if (rv != PAM_SUCCESS) {
+      release_pkcs11_module(ph);
+***************
+*** 558,564 ****
+    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));
+    rv = pam_putenv(pamh, env_temp);
+  
+    if (rv != PAM_SUCCESS) {
+--- 592,598 ----
+    snprintf(env_temp, sizeof(env_temp) - 1,
+  	   "PKCS11_LOGIN_TOKEN_NAME=%.*s", 
+  	   (sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_TOKEN_NAME="),
+! 	   get_slot_tokenlabel(ph));
+    rv = pam_putenv(pamh, env_temp);
+  
+    if (rv != PAM_SUCCESS) {
+*** pam_pkcs11-0.6.0-ORIG/src/pam_pkcs11/pam_config.c	Mon May 21 02:46:19 2007
+--- pam_pkcs11-WS/src/pam_pkcs11/pam_config.c	Mon Sep 28 16:06:48 2009
+***************
+*** 20,25 ****
+--- 20,26 ----
+  
+  #include <syslog.h>
+  #include <string.h>
++ #include "config.h"
+  #include "../scconf/scconf.h"
+  #include "../common/debug.h"
+  #include "../common/error.h"
+***************
+*** 27,38 ****
+--- 28,45 ----
+  #include "pam_config.h"
+  #include "mapper_mgr.h"
+  
++ #define N_(string) (string)
++ 
+  /*
+  * configuration related functions
+  */
+  
+  struct configuration_st configuration = {
++ #ifndef ORIGINAL /* SUN_SOLARIS */
++ 	"/etc/security/pam_pkcs11/pam_pkcs11.conf",
++ #else
+  	"/etc/pam_pkcs11/pam_pkcs11.conf",	/* char * config_file; */
++ #endif
+  	NULL,				/* scconf_context *ctx; */
+          0,				/* int debug; */
+          0,				/* int nullok; */
+***************
+*** 44,57 ****
+          "default", 			/* const char *pkcs11_module; */
+          "/etc/pam_pkcs11/pkcs11_module.so",/* const char *pkcs11_module_path; */
+          NULL,                           /* screen savers */
+!         0,				/* int slot_num; */
+  	0,				/* support threads */
+  	/* cert policy; */
+          { 0,CRLP_NONE,0,"/etc/pam_pkcs11/cacerts","/etc/pam_pkcs11/crls","/etc/pam_pkcs11/nssdb",OCSP_NONE },
+  	NULL				/* char *username */
+  };
+  
+- #if 0
+  static void display_config (void) {
+          DBG1("debug %d",configuration.debug);
+          DBG1("nullok %d",configuration.nullok);
+--- 51,65 ----
+          "default", 			/* const char *pkcs11_module; */
+          "/etc/pam_pkcs11/pkcs11_module.so",/* const char *pkcs11_module_path; */
+          NULL,                           /* screen savers */
+! 	NULL,				/* slot_description */
+!         -1,				/* int slot_num; */
+  	0,				/* support threads */
+  	/* cert policy; */
+          { 0,CRLP_NONE,0,"/etc/pam_pkcs11/cacerts","/etc/pam_pkcs11/crls","/etc/pam_pkcs11/nssdb",OCSP_NONE },
++ 	N_("Smart card"), 		/* token_type */
+  	NULL				/* char *username */
+  };
+  
+  static void display_config (void) {
+          DBG1("debug %d",configuration.debug);
+          DBG1("nullok %d",configuration.nullok);
+***************
+*** 71,77 ****
+          DBG1("signature_policy %d",configuration.policy.signature_policy);
+          DBG1("ocsp_policy %d",configuration.policy.ocsp_policy);
+  }
+- #endif
+  
+  /*
+  parse configuration file
+--- 79,84 ----
+***************
+*** 136,143 ****
+--- 143,164 ----
+  	        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");
+***************
+*** 165,170 ****
+--- 186,194 ----
+  	        }
+  		policy_list= policy_list->next;
+  	    }
++ 
++ 	    configuration.token_type = (char *)
++ 		scconf_get_str(pkcs11_mblk,"token_type",configuration.token_type);
+  	}
+  	screen_saver_list = scconf_find_list(root,"screen_savers");
+  	if (screen_saver_list) {
+***************
+*** 199,205 ****
+  	int i;
+  	int res;
+  	/* try to find a configuration file entry */
+! 	for (i = 0; i < argc; i++) {
+  	    if (strstr(argv[i],"config_file=") ) {
+  		configuration.config_file=1+strchr(argv[i],'=');
+  		break;
+--- 223,229 ----
+  	int i;
+  	int res;
+  	/* try to find a configuration file entry */
+! 	for (i = 1; i < argc; i++) {
+  	    if (strstr(argv[i],"config_file=") ) {
+  		configuration.config_file=1+strchr(argv[i],'=');
+  		break;
+***************
+*** 211,217 ****
+  	/* display_config(); */
+  	/* finally parse provided arguments */
+  	/* dont skip argv[0] */
+! 	for (i = 0; i < argc; i++) {
+  	   if (strcmp("nullok", argv[i]) == 0) {
+  		configuration.nullok = 1;
+  		continue;
+--- 235,241 ----
+  	/* display_config(); */
+  	/* finally parse provided arguments */
+  	/* dont skip argv[0] */
+! 	for (i = 1; i < argc; i++) {
+  	   if (strcmp("nullok", argv[i]) == 0) {
+  		configuration.nullok = 1;
+  		continue;
+***************
+*** 246,255 ****
+  		res=sscanf(argv[i],"pkcs11_module=%255s",configuration.pkcs11_module);
+  		continue;
+  	   }
+  	   if (strstr(argv[i],"slot_num=") ) {
+! 		res=sscanf(argv[i],"slot_nume=%d",&configuration.slot_num);
+  		continue;
+  	   }
+  	   if (strstr(argv[i],"ca_dir=") ) {
+  		res=sscanf(argv[i],"ca_dir=%255s",configuration.policy.ca_dir);
+  		continue;
+--- 270,285 ----
+  		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_num=%d",&configuration.slot_num);
+  		continue;
+  	   }
++ 
+  	   if (strstr(argv[i],"ca_dir=") ) {
+  		res=sscanf(argv[i],"ca_dir=%255s",configuration.policy.ca_dir);
+  		continue;
+***************
+*** 289,294 ****
+--- 319,330 ----
+  		}
+  		continue;
+  	   }
++ 
++ 	   if (strstr(argv[i],"token_type=") ) {
++ 		res=sscanf(argv[i],"token_type=%255s",configuration.token_type);
++ 		continue;
++ 	   }
++ 
+  	   if (strstr(argv[i],"config_file=") ) {
+  		/* already parsed, skip */
+  		continue;
+***************
+*** 299,302 ****
+  	}
+  	return &configuration;
+  }
+- 
+--- 335,337 ----
+*** pam_pkcs11-0.6.0-ORIG/src/mappers/ldap_mapper.c	Wed Jun  6 02:48:24 2007
+--- pam_pkcs11-WS/src/mappers/ldap_mapper.c	Mon Sep 28 16:06:48 2009
+***************
+*** 184,192 ****
+  	}
+  
+  # ifdef HAVE_LDAP_INIT
+! 	*ld = ldap_init (uri, defport);
+  # else
+! 	*ld = ldap_open (uri, defport);
+  # endif
+  	rc = (*ld == NULL) ? LDAP_SERVER_DOWN : LDAP_SUCCESS;
+  
+--- 184,192 ----
+  	}
+  
+  # ifdef HAVE_LDAP_INIT
+! 	*ld = ldap_init (uri, ldapdefport);
+  # else
+! 	*ld = ldap_open (uri, ldapdefport);
+  # endif
+  	rc = (*ld == NULL) ? LDAP_SERVER_DOWN : LDAP_SUCCESS;
+  
+*** pam_pkcs11-0.6.0-ORIG/src/tools/pkcs11_inspect.c	Mon May 21 02:46:19 2007
+--- pam_pkcs11-WS/src/tools/pkcs11_inspect.c	Mon Sep 28 16:06:48 2009
+***************
+*** 53,58 ****
+--- 53,63 ----
+  	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,85 ****
+    }
+  
+    /* open pkcs #11 session */
+!   rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+    if (rv != 0) {
+      release_pkcs11_module(ph);
+      DBG("no token available");
+--- 84,95 ----
+    }
+  
+    /* open pkcs #11 session */
+!   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");
+*** pam_pkcs11-0.6.0-ORIG/src/tools/pklogin_finder.c	Wed Jun  6 03:00:36 2007
+--- pam_pkcs11-WS/src/tools/pklogin_finder.c	Mon Sep 28 16:06:48 2009
+***************
+*** 55,60 ****
+--- 55,65 ----
+  	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,86 ****
+    }
+  
+    /* open pkcs #11 session */
+!   rv = find_slot_by_number(ph,configuration->slot_num, &slot_num);
+    if (rv != 0) {
+      release_pkcs11_module(ph);
+      DBG("no token available");
+--- 85,95 ----
+    }
+  
+    /* open pkcs #11 session */
+!   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");
+*** pam_pkcs11-0.6.0-ORIG/src/tools/pkcs11_eventmgr.c	Wed Jun  6 04:14:27 2007
+--- pam_pkcs11-WS/src/tools/pkcs11_eventmgr.c	Mon Sep 28 16:06:48 2009
+***************
+*** 430,435 ****
+--- 430,436 ----
+  	}
+      }
+  
++ #ifdef HAVE_DAEMON
+      if (daemonize) {
+  	DBG("Going to be daemon...");
+  	if ( daemon(0,debug)<0 ) {
+***************
+*** 440,445 ****
+--- 441,447 ----
+  		return 1;
+  	}
+      }
++ #endif 
+  
+      /* 
+       * Wait endlessly for all events in the list of readers
+***************
+*** 512,517 ****
+--- 514,520 ----
+      }
+  
+      /* put my self into background if flag is set */
++ #ifdef HAVE_DAEMON
+      if (daemonize) {
+  	DBG("Going to be daemon...");
+  	if ( daemon(0,debug)<0 ) {
+***************
+*** 521,526 ****
+--- 524,530 ----
+  		return 1;
+  	}
+      }
++ #endif 
+  
+      /* open pkcs11 sesion */
+      DBG("initialising pkcs #11 module...");
+*** pam_pkcs11-0.6.0-ORIG/src/tools/pkcs11_listcerts.c	Mon May 21 02:46:19 2007
+--- pam_pkcs11-WS/src/tools/pkcs11_listcerts.c	Mon Sep 28 16:06:48 2009
+***************
+*** 53,58 ****
+--- 53,63 ----
+  	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,84 ****
+    }
+  
+    /* open pkcs #11 session */
+!   rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+    if (rv != 0) {
+      release_pkcs11_module(ph);
+      DBG("no token available");
+--- 83,94 ----
+    }
+  
+    /* open pkcs #11 session */
+!   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");
+*** pam_pkcs11-0.6.0-ORIG/src/tools/pkcs11_setup.c	Wed Jun  6 04:20:09 2007
+--- pam_pkcs11-WS/src/tools/pkcs11_setup.c	Mon Sep 28 16:06:48 2009
+***************
+*** 60,65 ****
+--- 60,92 ----
+      return value;
+  }
+  
++ #ifndef ORIGINAL /* SUN_SOLARIS */
++ /* Written by Niels M\ufffd\ufffdller <[email protected]>
++  * modified by Ludovic Rousseau <[email protected]>
++  *
++  * This file is hereby placed in the public domain.
++  */
++ static char * strndup (const char *s, size_t size)
++ {
++ 	char *r;
++ 	char *end = memchr(s, 0, size);
++ 
++ 	if (NULL == end)
++ 		return NULL;
++ 
++ 	/* Length */
++ 	size = end - s;
++ 
++ 	r = malloc(size+1);
++ 	if (r)
++ 	{
++ 		memcpy(r, s, size);
++ 		r[size] = '\0';
++ 	}
++ 	return r;
++ }
++ #endif
++ 
+  static int scconf_replace_str_list(scconf_block * block, const char *option, const char *value)
+  {
+      scconf_list *list = NULL;
+*** pam_pkcs11-0.6.0-ORIG/tools/make_hash_link.sh	Mon May 21 02:46:19 2007
+--- pam_pkcs11-WS/tools/make_hash_link.sh	Mon Sep 28 16:06:48 2009
+***************
+*** 54,60 ****
+    hash=`$OPENSSL x509 -inform pem -in $file -noout -hash 2> /dev/null`
+    if [ ! -z $hash ]; then
+      is_ca=`$OPENSSL x509 -inform pem -in $file -noout -text | grep 'CA:TRUE'`
+!     if [ ! -z $is_ca ]; then
+        hash=$hash.
+        mk_link
+      fi
+--- 54,60 ----
+    hash=`$OPENSSL x509 -inform pem -in $file -noout -hash 2> /dev/null`
+    if [ ! -z $hash ]; then
+      is_ca=`$OPENSSL x509 -inform pem -in $file -noout -text | grep 'CA:TRUE'`
+!     if [ ! -z "$is_ca" ]; then
+        hash=$hash.
+        mk_link
+      fi
+***************
+*** 63,69 ****
+    hash=`$OPENSSL x509 -inform der -in $file -noout -hash 2> /dev/null`
+    if [ ! -z $hash ]; then
+      is_ca=`$OPENSSL x509 -inform der -in $file -noout -text | grep 'CA:TRUE'`
+!     if [ ! -z $is_ca ]; then
+        hash=$hash.
+        mk_link
+      fi
+--- 63,69 ----
+    hash=`$OPENSSL x509 -inform der -in $file -noout -hash 2> /dev/null`
+    if [ ! -z $hash ]; then
+      is_ca=`$OPENSSL x509 -inform der -in $file -noout -text | grep 'CA:TRUE'`
+!     if [ ! -z "$is_ca" ]; then
+        hash=$hash.
+        mk_link
+      fi