Commits

Huie-Ying Lee  committed b454e61

7050151 migrate pam_pkcs11 from sfw to userland

  • Participants
  • Parent commits 4a5d715
  • Tags build-168

Comments (0)

Files changed (6)

File components/meta-packages/history/SUNWpampkcs11.p5m

+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# Legacy package information for renamed SUNWpampkcs11 package
+#
+
+set name=pkg.fmri value=pkg:/SUNWpampkcs11@0.6.0,5.11-0.133
+set name=pkg.renamed value=true
+
+set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
+
+depend fmri=library/security/pam/module/pam-pkcs11@0.6.0-0.133 type=require 

File components/pam_pkcs11/Makefile

+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+#
+include ../../make-rules/shared-macros.mk
+
+COMPONENT_NAME=		pam_pkcs11
+COMPONENT_VERSION=	0.6.0
+COMPONENT_SRC=		$(COMPONENT_NAME)-$(COMPONENT_VERSION)
+COMPONENT_ARCHIVE=	$(COMPONENT_SRC).tar.gz
+COMPONENT_ARCHIVE_HASH=	sha1:eef40325afc426e5364f0d9762a8e0aded34a6c2
+COMPONENT_ARCHIVE_URL=	http://www.opensc-project.org/files/$(COMPONENT_NAME)/$(COMPONENT_ARCHIVE)
+
+include ../../make-rules/prep.mk
+include ../../make-rules/configure.mk
+include ../../make-rules/ips.mk
+
+CONFIGURE_OPTIONS +=	CFLAGS="$(CFLAGS)"
+CONFIGURE_OPTIONS += --with-pcsclite=no
+CONFIGURE_OPTIONS += --with-included-gettext=yes
+CONFIGURE_OPTIONS += --localstatedir=/var
+
+# common targets
+build:		$(BUILD_32_and_64)
+
+install:	$(INSTALL_32_and_64)
+
+test:		$(NO_TESTS)
+
+BUILD_PKG_DEPENDENCIES =	$(BUILD_TOOLS)
+
+include ../../make-rules/depend.mk

File components/pam_pkcs11/pam_pkcs11.conf

+#
+# Configuration file for pam_pkcs11 module
+#
+# Original Author: Juan Antonio Martinez <jonsito@teleline.es>
+#
+pam_pkcs11 {
+  # Allow empty passwords
+  nullok = true;
+
+  # Enable debugging support.
+  debug = true; 
+
+  # Filename of the PKCS #11 module. The default value is "default"
+  use_pkcs11_module = default;
+
+  pkcs11_module default {
+    module = /usr/lib/libpkcs11.so;
+    description = "Solaris PKCS#11 Cryptographic Framework library";
+
+    # Which slot to use?
+    # You can use "slot_description" or "slot_num", 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 PKCS#11 implementations that guarantee
+    # constant 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.
+    #
+    # On Solaris OS, an administrator can use the "cryotoadm list -v" command
+    # to find all the available slots and their slot descriptions. For more 
+    # information, see the libpkcs11(3LIB) and cryptoadm(1m) man pages.
+    #
+    slot_description = "none";
+
+    # Where are CA certificates stored?
+    # You can setup this value to:
+    # 1- A directory with openssl hash-links to all certificates
+    # 2- A CA file in PEM (.pem) or ASN1 (.cer) format, 
+    # containing all allowed CA certs
+    # The default value is /etc/security/pam_pkcs11/cacerts.
+    ca_dir = /etc/security/pam_pkcs11/cacerts;
+  
+    # Path to the directory where the local (offline) CRLs are stored.
+    # Same convention as above is applied: you can choose either
+    # hash-link directory or CRL file
+    # The default value is /etc/security/pam_pkcs11/crls.
+    crl_dir = /etc/security/pam_pkcs11/crls;
+  
+    # Some pcks#11 libraries can handle multithreading. So 
+    # set it to true to properly call C_Initialize() 
+    support_threads = false;
+
+    # Sets the Certificate verification policy. 
+    # "none"        Performs no verification
+    # "ca"          Does CA check
+    # "crl_online"  Downloads the CRL form the location given by the
+    #               CRL distribution point extension of the certificate
+    # "crl_offline" Uses the locally stored CRLs
+    # "crl_auto"    Is a combination of online and offline; it first 
+    #               tries to download the CRL from a possibly given CRL 
+    #               distribution point and if this fails, uses the local
+    #               CRLs
+    # "signature"   Does also a signature check to ensure that private
+    #               and public key matches
+    # You can use a combination of ca,crl, and signature flags, or just
+    # use "none".
+    # cert_policy = ca,signature;
+    cert_policy = signature;
+
+    # What kind of token?
+    # The value of the token_type parameter will be used in the user prompt
+    # messages.  The default value is "Smart card".
+    token_type = "Secure token";
+  }
+
+  # Which mappers ( Cert to login ) to use?
+  # you can use several mappers:
+  #
+  # subject - Cert Subject to login file based mapper
+  # pwent   - CN to getpwent() login or gecos fields mapper
+  # ldap    - LDAP mapper
+  # opensc  - Search certificate in ${HOME}/.eid/authorized_certificates
+  # openssh - Search certificate public key in ${HOME}/.ssh/authorized_keys
+  # mail    - Compare email fields from certificate
+  # ms      - Use Microsoft Universal Principal Name extension
+  # krb     - Compare againts Kerberos Principal Name
+  # cn      - Compare Common Name (CN)
+  # uid     - Compare Unique Identifier
+  # digest  - Certificate digest to login (mapfile based) mapper
+  # generic - User defined certificate contents mapped
+  # null    - blind access/deny mapper
+  #
+  # You can select a comma-separated mapper list.
+  # If used null mapper should be the last in the list :-)
+  # Also you should select at least one mapper, otherwise
+  # certificate will not match :-)
+  # use_mappers = digest, cn, pwent, uid, mail, subject, null;
+  use_mappers = cn;
+
+  # When no absolute path or module info is provided, use this
+  # value as module search path
+  # TODO:
+  # This is not still functional: use absolute pathnames or LD_LIBRARY_PATH 
+  mapper_search_path = /usr/lib/pam_pkcs11;
+
+  # 
+  # Generic certificate contents mapper
+  mapper generic {
+        debug = true;
+        module = internal;
+        # ignore letter case on match/compare
+        ignorecase = false;
+        # Use one of "cn" , "subject" , "kpn" , "email" , "upn" or "uid"
+        cert_item  = cn;
+        # Define mapfile if needed, else select "none"
+        mapfile = file:///etc/security/pam_pkcs11/generic_mapping
+        # Decide if use getpwent() to map login
+        use_getpwent = false;
+  }
+
+  # Certificate Subject to login based mapper
+  # provided file stores one or more "Subject -> login" lines
+  mapper subject {
+	debug = false;
+	module = internal;
+	ignorecase = false;
+	mapfile = file:///etc/security/pam_pkcs11/subject_mapping;
+  }
+
+  # Search public keys from $HOME/.ssh/authorized_keys to match users
+  mapper openssh {
+	debug = false;
+	module = /usr/lib/pam_pkcs11/openssh_mapper.so;
+  }
+
+  # Search certificates from $HOME/.eid/authorized_certificates to match users
+  mapper opensc {
+	debug = false;
+	module = /usr/lib/pam_pkcs11/opensc_mapper.so;
+  }
+
+  # Certificate Common Name ( CN ) to getpwent() mapper
+  mapper pwent {
+	debug = false;
+	ignorecase = false;
+	module = internal;
+  }
+
+  # Null ( no map ) mapper. when user as finder matchs to NULL or "nobody"
+  mapper null {
+	debug = false;
+	module = internal ;
+	# select behavior: always match, or always fail
+	default_match = false;
+	# on match, select returned user
+        default_user = nobody ;
+  }
+
+  # Directory ( ldap style ) mapper
+  mapper ldap {
+	debug = false;
+	module = /usr/lib/pam_pkcs11/ldap_mapper.so;
+	# hostname of ldap server (use LDAP-URI for more then one)
+	ldaphost = "";
+	# Port on ldap server to connect, this is also the default
+	#   if no port is given in URI below
+	#   if empty, then 389 for TLS and 636 for SSL is used
+	ldapport = ;
+	# space separted list of LDAP URIs (URIs are used by given order)
+	URI = "";
+	# Scope of search: 0-2
+	#   Default is 1 = "one", meaning the set of records one
+	#   level below the basedn.
+	#   0 = "base"  means search only the basedn, and
+	#   2 = "sub"  means the union of entries at the "base" level
+	#   and ? all or "one" level below ??? FIXME
+	scope = 2;
+	# DN to bind with. Must have read-access for user entries
+	# under "base"
+	binddn = "cn=pam,o=example,c=com";
+	# Password for above DN
+	passwd = "";
+	# Searchbase for user entries
+	base = "ou=People,o=example,c=com";
+	# Attribute of user entry which contains the certificate
+	attribute = "userCertificate";
+	# Searchfilter for user entry. Must only let pass user entry
+	# for the login user.
+	filter = "(&(objectClass=posixAccount)(uid=%s))"
+	# SSL/TLS-Switch
+	#   This is a global switch, you can't switch between
+	#   SSL or TLS and non secured connections per URI!
+	#   values: off (standard), tls or on (ssl) or ssl
+	ssl = tls
+	# SSL specific settings
+	# tls_randfile = ...
+	tls_cacertfile = /etc/ssl/cacert.pem
+	# tls_cacertdir = ...
+	tls_checkpeer = 0
+	#tls_ciphers = ...
+	#tls_cert = ...
+	#tls_key = ...
+  }
+
+  # Assume common name (CN) to be the login
+  mapper cn {
+	debug = false;
+	module = internal;
+	ignorecase = true;
+	# mapfile = file:///etc/security/pam_pkcs11/cn_map;
+	mapfile = "none";
+  }
+
+  # mail -  Compare email field from certificate
+  mapper mail {
+	debug = false;
+	module = internal;
+	# Declare mapfile or
+	# leave empty "" or "none" to use no map 
+	mapfile = file:///etc/security/pam_pkcs11/mail_mapping;
+	# Some certs store email in uppercase. take care on this
+	ignorecase = true;
+	# Also check that host matches mx domain
+	# when using mapfile this feature is ignored
+	ignoredomain = false;
+  }
+
+  # ms - Use Microsoft Universal Principal Name extension
+  # UPN is in format login@ADS_Domain. No map is needed, just
+  # check domain name.
+  mapper ms {
+	debug = false;
+	module = internal;
+	ignorecase = false;
+	ignoredomain = false;
+	domain = "domain.com";
+  }
+
+  # krb  - Compare againts Kerberos Principal Name
+  mapper krb {
+	debug = false;
+	module = internal;
+	ignorecase = false;
+	mapfile = "none";
+  }
+
+  # uid  - Maps Subject Unique Identifier field (if exist) to login
+  mapper uid {
+	debug = false;
+	module = internal;
+	ignorecase = false;
+	mapfile = "none";
+  }
+
+  # digest - elaborate certificate digest and map it into a file
+  mapper digest {
+	debug = false;
+	module = internal;
+	# algorithm used to evaluate certificate digest
+        # Select one of:
+	# "null","md2","md4","md5","sha","sha1","dss","dss1","ripemd160"
+	algorithm = "sha1";
+	# mapfile = file:///etc/security/pam_pkcs11/digest_mapping;
+	mapfile = "none";
+
+  }
+
+}

File components/pam_pkcs11/pam_pkcs11.license

+Oracle elects to use only the GNU Lesser General Public License version
+2.1 (LGPL)/GNU General Public License version 2 (GPL) for any software
+where a choice of LGPL/GPL license versions are made available with the
+language indicating that LGPLv2.1/GPLv2 or any later version may be
+used, or where a choice of which version of the LGPL/GPL is applied is
+unspecified.  Unless specifically stated otherwise, where a choice
+exists between another license and either the GPL or the LGPL, Oracle
+chooses the other license.
+-----------------------------------------------------------------------
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!

File components/pam_pkcs11/pam_pkcs11.p5m

+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+#
+
+set name=pkg.fmri \
+    value=pkg:/library/security/pam/module/pam-pkcs11@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
+set name=pkg.summary value="The OpenSC PKCS#11 PAM Login Tools"
+set name=info.classification \
+    value="org.opensolaris.category.2008:System/Security"
+set name=info.source_url value=$(COMPONENT_ARCHIVE_URL)
+set name=info.upstream_url value=http://www.opensc-project.org
+set name=opensolaris.arc_url \
+    value=http://arc.opensolaris.org/caselog/PSARC/2006/283
+set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
+
+dir path=etc
+dir path=etc/security
+dir path=etc/security/pam_pkcs11
+dir path=etc/security/pam_pkcs11/cacerts
+dir path=etc/security/pam_pkcs11/crls
+dir path=usr
+dir path=usr/lib
+dir path=usr/lib/pam_pkcs11
+dir path=usr/lib/pam_pkcs11/$(MACH64)
+dir path=usr/lib/security
+dir path=usr/lib/security/$(MACH64)
+dir path=usr/share
+dir path=usr/share/doc
+dir path=usr/share/doc/pam_pkcs11
+dir path=usr/share/locale
+dir path=usr/share/locale/fr
+dir path=usr/share/locale/fr/LC_MESSAGES
+
+file pam_pkcs11.conf path=etc/security/pam_pkcs11/pam_pkcs11.conf mode=0644 \
+    preserve=renamenew \
+    original_name=SUNWpampkcs11:etc/security/pam_pkcs11/pam_pkcs11.conf
+file usr/bin/make_hash_link.sh \
+    path=etc/security/pam_pkcs11/make_hash_link.sh mode=0555
+file usr/share/pam_pkcs11/digest_mapping.example \
+    path=etc/security/pam_pkcs11/digest_mapping.example 
+file usr/share/pam_pkcs11/mail_mapping.example \
+    path=etc/security/pam_pkcs11/mail_mapping.example
+file usr/share/pam_pkcs11/subject_mapping.example \
+    path=etc/security/pam_pkcs11/subject_mapping.example
+file usr/bin/pkcs11_inspect path=usr/lib/pam_pkcs11/pkcs11_inspect mode=0555
+file usr/bin/pklogin_finder path=usr/lib/pam_pkcs11/pklogin_finder mode=0555
+file usr/lib/security/pam_pkcs11.so path=usr/lib/security/pam_pkcs11.so 
+file usr/lib/$(MACH64)/security/pam_pkcs11.so \
+    path=usr/lib/security/$(MACH64)/pam_pkcs11.so
+file path=usr/lib/pam_pkcs11/ldap_mapper.so
+file path=usr/lib/pam_pkcs11/opensc_mapper.so
+file path=usr/lib/pam_pkcs11/openssh_mapper.so
+file usr/lib/$(MACH64)/pam_pkcs11/ldap_mapper.so \
+    path=usr/lib/pam_pkcs11/$(MACH64)/ldap_mapper.so
+file usr/lib/$(MACH64)/pam_pkcs11/opensc_mapper.so \
+    path=usr/lib/pam_pkcs11/$(MACH64)/opensc_mapper.so
+file usr/lib/$(MACH64)/pam_pkcs11/openssh_mapper.so \
+    path=usr/lib/pam_pkcs11/$(MACH64)/openssh_mapper.so 
+file path=usr/share/locale/fr/LC_MESSAGES/pam_pkcs11.mo
+file doc/pam_pkcs11.html path=usr/share/doc/pam_pkcs11/pam_pkcs11.html
+file doc/mappers_api.html path=usr/share/doc/pam_pkcs11/mappers_api.html
+
+legacy pkg=SUNWpampkcs11u desc="The OpenSC PKCS#11 PAM Login Tools 0.6.0" \
+    name="The OpenSC PKCS#11 PAM Login Tools"
+legacy pkg=SUNWpampkcs11r desc="The OpenSC PKCS#11 PAM Login Tools 0.6.0" \
+    name="The OpenSC PKCS#11 PAM Login Tools"
+legacy pkg=SUNWpampkcs11-docs desc="The OpenSC PKCS#11 PAM Login Tools 0.6.0" \
+    name="The OpenSC PKCS#11 PAM Login Tools"
+
+license pam_pkcs11.license license=LGPLv2.1

File components/pam_pkcs11/patches/pam_pkcs11.patch

+*** 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 ----
+    }