What is a cert mapper?
----------------------

When an X509 Certificate is provided, there are no direct way to map
a cert to a login. With a certificate we can check validity and
revocation, but user mapping depends entirely on the certificate content.

So we need a configurable, stackable, and definable way to specify
cert-to-user mapping.

pam-pkcs11 cert mappers provides several functions:

1- Deduce a login from certificate
2- Test if a login and a certificate match
3- Look into the certificate for an specific data

Normal pam-pkcs11 login process involves the following procedures
    - Enter login
    - Ask for PIN
    - Open and validate certificate
    - Map certificate into an user (*)
    - Check if login and user matches (**)

An alternate way of working is by mean of not providing user name:
    - Detect if a card is inserted
    - Ask for PIN
    - Open and validate certificate
    - Map certificate into an user (*)
    - open session for deduced login

Last way needs an additional pam-mkhomedir.so PAM module, that can
dynamically create an account.

Operations (*) and (**) are the reason for cert-mappers to exist.


Implementation of cert mappers in pam-pkcs11
--------------------------------------------

pam-pkcs11 implements cert mapper in form of several stackable modules.
Most of them are statically linked; those that depends on external
libraries are provided as dynamic loadable ones

You can add as many modules as desired, and the system will try all
of them in turn, until a match succeed, or end of list is reached.

the mapper list is defined in the configuration file:

pam-pkcs11 {
    ....
    mapper_list = mapper1 [ [[,] mapper2 ] ... ] ;

    mapper mapper1 {
        module = /path/to/module.so;
        [ additional mapper dependent options ]
    }
}

Unless you are going to use an internal (static) module with
default values, you should provide a entry for every declared mapper

"module" entry is mandatory: is tells pam_pkcs11 where to find the
dynamic library (or equals to "internal" if static module is used). 
Additional entries can be defined but are module dependent.


Provided Mappers
----------------

Actually pam_opensc provides the following mapper modules:

cn     - Assumes CN field on certificate to be the login name
		* When used as finder, the module returns the first CN field
		  found or NULL
		* When used as matcher, it parses the certificate and compare
		  all CN fields found against the provided login name, returning
		  OK if a match is found

file   - Parse a file to get a list of CN -> login pairs
		* When used as finder, retrieve first CN field on certificate,
		  and use it to read provided file to get a CN to login mapping
		* When used as matcher, maps every CN entry on the certificate
		  to a login, and compare this login with provided by PAM

pw     - Compare CN against getpwent() "login" or "gecos" fields to match
         user login
        * When used as finder use getpwent() system call to retrieve every
          users on the system. if pw_name or pw_gecos fields match with CN
          pw_name is returned as login name
        * When used as matcher, maps CN to an user with via the finder
          and matches result with login name provided by PAM, returning the
          result (match or not)

        Note: newer implementations of getpwent() libraries, use an
        additional Name Service Switch (NSS) infrastructure, that
        allows admins to specify how to obtain the requested data.
        This means you can setup /etc/nsswitch.conf password entries
        to lookup in to /etc/passwd, or ldap/kerberos/NIS+/YP services

ldap   - Uses an ldap server to retrieve user name. An additional file tells
         module the mapping between Cert fields and LDAP entries

        This mapper is still under development. Provided one just search
	for certificates, incoming one will ask for "any" certificate
	content

opensc - Search the certificate ${HOME}/.ssh/autorized_certificates 
	in a similar way as OpenSC does.

openssh - Search the certificate public key in
	 ${HOME}/.ssh/autorized_keys in a similar way as OpenSSH does.

mail   - Try to extract an e-mail from the certificate. If found,
         analyze it against an "aliases" (email to login) list

        if "use_alias" is set an aliases file is provided, the module 
        tries to map the email field from the certificate to a user 
        (or alternate email).

        if use_alias is not set, just use email address from certificate
        to perform find/match.

        * When used as finder, just return email or mapped email/user
          (see above)
		* When used as matcher, compare found email/user against
		  provided by pam. Additionally you can set "ignorecase" or
		  "ignoredomain" flags

        domain check (if set) is done by testing if provided email domain
        part (@ie.this.domain) matches host domain. 
        Eg "user@my.company.com" email in host "ahost.in.my.company.com" 
        host matches domain

       (NOTE: at version 0.4.1 use_alias is still under development)

ms     - Try to find and use Microsoft Universal Principal Name extension 
         as login name
        * When used as finder, returns UPN as login name
        * when used as matcher compares UPN against PAM provided login

krb    - Try to find and use Kerberos Principal Name as login name

uid    - Use Unique ID field (if found) as login name

        Similar to CN mapper, but using UID as field to find/match

null   - blind access/deny mapper. 

        If "always_match" is set to true:
        * When used as finder always returns "nobody"
        * When used as matcher always returns OK

        If "always_match" is set to false:
        * When used as finder always returns NULL
        * When used as matcher always returns FAIL

See the provided pam_pkcs11.conf.example file to see module flags


Adding new mappers
------------------

Creating new mappers is easy: just read provided Mapper API file, 
edit skeleton sample files and follow instructions on how to compile
and link

Mapper.h provides default implementation for required some functions. 
They should be overridden by user code, but can be used for testing purposes

Wish list
---------

- Implement PKINIT draft protocol for talking to a kerberos server
- Use MS Universal Principal Name to authenticate against an MS Active
  directory server
- Implement mail_aliases parsing for mail mapper module

Further information
-------------------
Please, send mail with patches, comments and suggestions to
Juan Antonio Martinez <jonsito@teleline.es> or even better, to
OpenSC development mailing list opensc-devel@list.opensc-project.org

