Bug 1267021

Summary: pklogin_finder fails when using ldap mapper communicating to tls enabled ldap instance
Product: Red Hat Enterprise Linux 7 Reporter: Roshni <rpattath>
Component: pam_pkcs11Assignee: Bob Relyea <rrelyea>
Status: CLOSED NOTABUG QA Contact: Asha Akkiangady <aakkiang>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.2   
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-01-12 19:41:13 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Roshni 2015-09-28 20:39:29 UTC
Description of problem:
pklogin_finder fails when using ldap mapper communicating to tls enabled ldap instance

Version-Release number of selected component (if applicable):
pam_pkcs11-0.6.2-24.el7

How reproducible:
always

Steps to Reproduce:
1. Configure a tls enabled ldap instance having the user to be enrolled to the smartcard
2. Configure pam_pkcs11.conf as follows

[root@dhcp129-45 ~]# cat /etc/pam_pkcs11/pam_pkcs11.conf
#
# Configuration file for pam_pkcs11 module
#
# Version 0.4
# Author: Juan Antonio Martinez <jonsito>
#
pam_pkcs11  {
    # Allow empty passwords
    nullok = true;

    # Enable debugging support.
    debug = false;

    # If the smart card is inserted, only use it
    card_only = true;

    # Do not prompt the user for the passwords but take them from the
    # PAM_ items instead.
    use_first_pass = false;

    # Do not prompt the user for the passwords unless PAM_(OLD)AUTHTOK
    # is unset.
    try_first_pass = false;

    # Like try_first_pass, but fail if the new PAM_AUTHTOK has not been
    # previously set (intended for stacking password modules only).
    use_authtok = false;

    # Filename of the PKCS #11 module. The default value is "default"
    use_pkcs11_module = coolkey;

    screen_savers = "gnome-screensaver", xscreensaver, kscreensaver;

    pkcs11_module coolkey {
        module = libcoolkeypk11.so;
        description = "Cool Key";
        # Slot-number to use. One for the first, two for the second and so
        # on. The default value is zero which means to use the first slot
        # with an available token.
        slot_num = 0;

        # Path to the directory where the CA certificates are stored. The
        # directory must contain an openssl hash-link to each certificate.
        # The default value is /etc/pam_pkcs11/cacerts.
        ca_dir = "/etc/pam_pkcs11/cacerts";
        nss_dir = /etc/pki/nssdb;

        # Path to the directory where the CRLs are stored. The directory
        # must contain an openssl hash-link to each CRL. The default value
        # is /etc/pam_pkcs11/crls.
        crl_dir = "/etc/pam_pkcs11/crls";

        # 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
        # "ocsp_on"     Turn on OCSP.
        # "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;
    }

    pkcs11_module opensc {
        module = "opensc-pkcs11.so";
        description = "OpenSC PKCS#11 module";
        # Slot-number to use. One for the first, two for the second and so
        # on. The default value is zero which means to use the first slot
        # with an available token.
        slot_num = 0;

        # Path to the directory where the CA certificates are stored. The
        # directory must contain an openssl hash-link to each certificate.
        # The default value is /etc/pam_pkcs11/cacerts.
        ca_dir = "/etc/pam_pkcs11/cacerts";

        # Path to the directory where the CRLs are stored. The directory
        # must contain an openssl hash-link to each CRL. The default value
        # is /etc/pam_pkcs11/crls.
        crl_dir = "/etc/pam_pkcs11/crls";

        # Sets the Certificate Policy, (see above)
        cert_policy = ca, signature;
    }

    # Default pkcs11 module
    pkcs11_module default {
        module = "/usr/$LIB/pam_pkcs11/pkcs11_module.so";
        description = "Default pkcs#11 module";
        slot_num = 0;
        ca_dir = "/etc/pam_pkcs11/cacerts";
        crl_dir = "/etc/pam_pkcs11/crls";
        cert_policy = ca, signature;
    }

    # 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 = ldap;

    # 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 = "/usr/$LIB/pam_pkcs11/generic_mapper.so";
        # 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/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 = /usr/$LIB/pam_pkcs11/subject_mapper.so;
        module = internal;
        ignorecase = false;
        mapfile = "file:///etc/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;
        # module = /usr/$LIB/pam_pkcs11/pwent_mapper.so;
    }

    # Null ( no map ) mapper. when user as finder matchs to NULL or "nobody"
    mapper null {
        debug = false;
        # module = /usr/$LIB/pam_pkcs11/null_mapper.so;
        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 = true;
        module = "/usr/$LIB/pam_pkcs11/ldap_mapper.so";
        # where base directory resides
        basedir = "/etc/pam_pkcs11/mapdir";
        # hostname of ldap server
        ldaphost = ibm-x3650m4-02-vm-04.lab.eng.bos.redhat.com;
        # Port on ldap server to connect
        ldapport = <ldaps-port>;
        # Scope of search: 0 = x, 1 = y, 2 = z
        scope = 2;
        # DN to bind with. Must have read-access for user entries under "base"
        binddn = "cn=Directory Manager";
        # Password for above DN
        passwd = Secret123;
        # Searchbase for user entries
        base = "ou=People,dc=pki-tps";
        # Attribute of user entry which contains the certificate
        attribute = userCertificate;
        # Searchfilter for user entry. Must only let pass user entry for the login user.
        uid_attribute = "uid";
        attribute_map = "uid=uid&mail=email", "redhatPrincipalName=upn", "userCertificate;binary=cert";
        filter = "(&(objectClass=posixAccount)(uid=%s))";
    }

    # Assume common name (CN) to be the login
    mapper cn {
        debug = false;
        module = internal;
        # module = /usr/$LIB/pam_pkcs11/cn_mapper.so;
        ignorecase = true;
        mapfile = "file:///etc/pam_pkcs11/cn_map";
    }

    # mail -  Compare email field from certificate
    mapper mail {
        debug = false;
        module = internal;
        # module = /usr/$LIB/pam_pkcs11/mail_mapper.so;
        # Declare mapfile or
        # leave empty "" or "none" to use no map
        mapfile = "file:///etc/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;
        # module = /usr/$LIB/pam_pkcs11/ms_mapper.so;
        ignorecase = false;
        ignoredomain = false;
        domain = domain.com;
    }

    # krb  - Compare againts Kerberos Principal Name
    mapper krb {
        debug = false;
        module = internal;
        # module = /usr/$LIB/pam_pkcs11/krb_mapper.so;
        ignorecase = false;
        mapfile = none;
    }

    # uid  - Maps Subject Unique Identifier field (if exist) to login
    mapper uid {
        debug = false;
        module = internal;
        # module = /usr/$LIB/pam_pkcs11/uid_mapper.so;
        ignorecase = false;
        mapfile = none;
    }

    # digest - elaborate certificate digest and map it into a file
    mapper digest {
        debug = false;
        module = internal;
        # module = /usr/$LIB/pam_pkcs11/digest_mapper.so;
        # algorithm used to evaluate certificate digest
        # Select one of:
        # "null","md2","md4","md5","sha","sha1","dss","dss1","ripemd160"
        algorithm = sha1;
        mapfile = "file:///etc/pam_pkcs11/digest_mapping";
        # mapfile = "none";
    }

} 

3. /etc/openldap/ldap.conf is configured as follows

[root@dhcp129-45 ~]# cat /etc/openldap/ldap.conf
#
# LDAP Defaults
#

# See ldap.conf(5) for details
# This file should be world readable but not world writable.

#BASE    dc=example,dc=com
#URI    ldap://ldap.example.com ldap://ldap-master.example.com:666

#SIZELIMIT    12
#TIMELIMIT    15
#DEREF        never

TLS_CACERTDIR /etc/openldap/certs
TLS_CACERT /etc/openldap/certs/ca_cert.pem

# Turning this off breaks GSSAPI used with krb5 when rdns = false
#SASL_NOCANON    on
URI ldaps://ibm-x3650m4-02-vm-04.lab.eng.bos.redhat.com:<ldaps-port>
BASE dc=pki-tps

The CA cert has been trusted in the location specified and also under /etc/pki/nssdb 

Actual results:
[root@dhcp129-45 ~]# pklogin_finder debug
DEBUG:pam_config.c:238: Using config file /etc/pam_pkcs11/pam_pkcs11.conf
DEBUG:pkcs11_lib.c:182: Initializing NSS ...
DEBUG:pkcs11_lib.c:192: Initializing NSS ... database=/etc/pki/nssdb
DEBUG:pkcs11_lib.c:210: ...  NSS Complete
DEBUG:pklogin_finder.c:71: loading pkcs #11 module...
DEBUG:pkcs11_lib.c:235: Looking up module in list
DEBUG:pkcs11_lib.c:238: modList = 0x1baa6f0 next = 0x1bb6220

DEBUG:pkcs11_lib.c:239: dllName= <null>

DEBUG:pkcs11_lib.c:238: modList = 0x1bb6220 next = 0x0

DEBUG:pkcs11_lib.c:239: dllName= libcoolkeypk11.so

DEBUG:pklogin_finder.c:79: initialising pkcs #11 module...
PIN for token:
DEBUG:pkcs11_lib.c:48: PIN = [redhat123]
DEBUG:pkcs11_lib.c:759: cert 0: found (pkiuser123:signing key for pkiuser123), "UID=pkiuser123,O=Token Key User"
DEBUG:mapper_mgr.c:172: Retrieveing mapper module list
DEBUG:mapper_mgr.c:95: Loading dynamic module for mapper 'ldap'
DEBUG:ldap_mapper.c:1172: test ssltls = default
DEBUG:ldap_mapper.c:1174: LDAP mapper started.
DEBUG:ldap_mapper.c:1175: debug         = 1
DEBUG:ldap_mapper.c:1176: ignorecase    = 0
DEBUG:ldap_mapper.c:1177: ldaphost      = ibm-x3650m4-02-vm-04.lab.eng.bos.redhat.com
DEBUG:ldap_mapper.c:1178: ldapport      = 1607
DEBUG:ldap_mapper.c:1179: ldapURI       =
DEBUG:ldap_mapper.c:1180: scope         = 2
DEBUG:ldap_mapper.c:1181: binddn        = cn=Directory Manager
DEBUG:ldap_mapper.c:1182: passwd        = Secret123
DEBUG:ldap_mapper.c:1183: base          = ou=People,dc=pki-tps
DEBUG:ldap_mapper.c:1184: attribute     = userCertificate
DEBUG:ldap_mapper.c:1185: uid_attribute = uid
DEBUG:ldap_mapper.c:1187: attribute_map = uid=uid&mail=email
DEBUG:ldap_mapper.c:1187: attribute_map = redhatPrincipalName=upn
DEBUG:ldap_mapper.c:1187: attribute_map = userCertificate;binary=cert
DEBUG:ldap_mapper.c:1189: filter        = (&(objectClass=posixAccount)(uid=%s))
DEBUG:ldap_mapper.c:1190: searchtimeout = 20
DEBUG:ldap_mapper.c:1191: ssl_on        = 0
DEBUG:ldap_mapper.c:1193: tls_randfile  =
DEBUG:ldap_mapper.c:1194: tls_cacertfile=
DEBUG:ldap_mapper.c:1195: tls_cacertdir =
DEBUG:ldap_mapper.c:1196: tls_checkpeer = -1
DEBUG:ldap_mapper.c:1197: tls_ciphers   =
DEBUG:ldap_mapper.c:1198: tls_cert      =
DEBUG:ldap_mapper.c:1199: tls_key       =
DEBUG:mapper_mgr.c:197: Inserting mapper [ldap] into list
DEBUG:pklogin_finder.c:127: Found '1' certificate(s)
DEBUG:pklogin_finder.c:131: verifing the certificate #1
DEBUG:cert_vfy.c:34: Verifying Cert: pkiuser123:signing key for pkiuser123 (UID=pkiuser123,O=Token Key User)
DEBUG:pklogin_finder.c:145: Trying to deduce login from certificate
DEBUG:ldap_mapper.c:931: ldap_get_certificate(): begin login unknown
DEBUG:ldap_mapper.c:582: added URI ldap://ibm-x3650m4-02-vm-04.lab.eng.bos.redhat.com:1607
DEBUG:ldap_mapper.c:991: ldap_get_certificate(): try do_open for ldap://ibm-x3650m4-02-vm-04.lab.eng.bos.redhat.com:1607
DEBUG:ldap_mapper.c:145: do_init():
DEBUG:ldap_mapper.c:415: Set connection timeout to 8
DEBUG:ldap_mapper.c:323: do_bind(): bind DN="cn=Directory Manager" pass="Secret123"
DEBUG:ldap_mapper.c:364: do_bind rc=0
DEBUG:ldap_mapper.c:369: do_bind return -1
DEBUG:ldap_mapper.c:543: do_open(): failed to bind to LDAP server ldap://ibm-x3650m4-02-vm-04.lab.eng.bos.redhat.com:1607: Can't contact LDAP server
DEBUG:ldap_mapper.c:1005: ldap_get_certificate(): do_open failed
DEBUG:ldap_mapper.c:1221: ldap_get_certificate() failed
DEBUG:pklogin_finder.c:148: find_user() failed:
DEBUG:mapper_mgr.c:214: unloading mapper module list
DEBUG:mapper_mgr.c:137: calling mapper_module_end() ldap
DEBUG:mapper_mgr.c:145: unloading module ldap
DEBUG:pklogin_finder.c:169: releasing pkcs #11 module...
DEBUG:pklogin_finder.c:172: Process completed


Expected results:
pklogin_finder should be successful

Additional info:

Comment 4 Roshni 2016-01-12 19:41:13 UTC
Based on /usr/share/doc/pam_pkcs11/pam_pkcs11.conf.example when pam_pkcs11.conf was configured with ssl=tls and non-secure port was used (similar changes were made to the port in ldap.conf), pklogin returned results as expected.