Name  : PAM module for MuscleCard Framework
Author: Eirik A. Herskedal, David Corcoran, Martin Saegesser

We support two modes for authentication. Which mode is used can be
determined in the configuration file. 


Method 1:

- Create a nonce on the host
- Request and Verify PIN #1
- Compute Crypt of the nonce with RSA 1024 bit key #3
- Get the user's certificate from the user's home directory
- Decrypt the nonce using the user's public key
- Compare the original nonce with the last


Method 2:

- Create a nonce on the host
- Request and Verify PIN #1
- Compute Crypt of the nonce with RSA 1024 bit key #3
- Get the user's certificate from the smartcard
- Verify the users certificate using the root CA certificate in /etc/root.cert
- Extract the users public key from the certificate
- Decrypt the nonce using the user's public key
- Compare the original nonce with the last


Installation:

type make
copy the library into /lib/security and edit your pam.conf file
or your service configuration file for PAM.


Configuration

There is a configuration file located in /etc/musclepam/pam-muscle.conf.
This will have parameters that are read by the authentication module.
Most of these are self-explanatory, except AuthMode. This parameter can
have two values:

1. UserCert -   the module will look in ~/.muscle/user.cert for the 
                certificate. If the file contains a value for UserPath, then
                this is used instead of the user's home directory. This allows
                the admin to create a directory containing certificates that
                are not modify able by the user. Of it can be used for testing.

2. RootCert -   the module will retreive the certificate from the smartcard 
                and validate the signature by looking at the RootCA's
                certificate in /etc/root.cert. It will also check that the
                username corresponds to the username in the certificate. 
                


If UserCert is selected, then the certificate can be in one of three formats.
    1) DER/BER X509 - this is a binary format
    2) PEM X509 (PEM_read_X509) - in PEM format

    This is in base64 format, and has the form
        -----BEGIN CERTIFICATE-----
        MIIEzzCCA7egAwIBAgIBADANBgkqhkiG9w0BAQQFADBvMQswCQYDVQQGEwJkZTEg
        [snip]
        -----END CERTIFICATE-----

    3) PEM - PUBKEY

    This is also in base64 format, and has the form
        -----BEGIN PUBLIC KEY-----
        MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhs17bA92YPg8XrR9s34qoK2Fc
        [snip]
        -----END PUBLIC KEY-----

        
    The third form can be obtained by using musacletool to create a
    keypair, export it, and then using b2fs to convert it into a
    pubkey format

    Example

    $ muscleTool
    muscle > tokens
       1.    MuscleCard Applet
    muscle > connect 1
    muscle [MuscleCard Applet] > verify 1 <PINVALUE>
    PIN Verify Successful
    muscle [MuscleCard Applet] > genkeys
    ***************** Key Generation Routine *****************
    Note: Keys will be generated with default permissions
               using the RSA CRT algorithm for generation.
    **********************************************************
    Enter the private key number: 1
    Enter the public key number: 2
    Are you sure ? (Y/N): y
    Generating keys 
    *******************************] : Success
    muscle [MuscleCard Applet] > listkeys
                Key Type      Key Num   SIZE     READ   WRITE     USE
       -----------------  -----------   -----   ------  ------  ------
         RSA PRIVATE CRT            1   1024     NEVER  PIN #1  PIN #1
              RSA PUBLIC            2   1024    ALWAYS  PIN #1  PIN #1
    muscle [MuscleCard Applet] > exportkey 2 cert.blob
    Export Key Successful
    muscle [MuscleCard Applet] > release
    muscle > exit

    # now use b2fs to convert the blob into a PEM public key certificate
    % b2fs cert.blob >~/.muscle/user.cert


        Also not that you have to change the certificate number from 0
        (which is the private key) to 1, which would in this case be the
        public key.

Note that the user can do this without any outside authority. 

The pam module makes sure that only the user and root has write access
to the certificate.  The certificate, and all of the directories
above, cannot be group or world writable, and have to be owned by the
user or root. Otherwise, the user is not allowed to log in, and a log
message is written to the log file.

Once you have the certificate in place, you can use PAM to add
smartcard authentication to the following modules [I have verified
that these work on Fedora Core 1. Other applications might work as
well, but I have not tested them.  -Bruce]

        login
        su
        xscreensaver
        gdm
        gdm-autologin


The modifications to the /etc/pam.d/* files only change the auth
values (lines whose first column is "auth")

Gdm can be configured in several ways.

Variation #1: If the reader is present, and the token inserted
                only ask for the PIN, and not the password
                If the reader or token is not present, ask for the password
------------
auth       sufficient   pam_musclecard.so service=system-auth debug
auth       required     pam_stack.so service=system-auth
-------------

Variation #2: Only use the smartcard, never the password
------------
auth       required     pam_musclecard.so service=system-auth debug
#auth       required     pam_stack.so service=system-auth
-------------
 

Variation #3: Require a password (first) and a pin (second)
------------
auth       required     pam_stack.so service=system-auth
auth       required     pam_musclecard.so service=system-auth debug
-------------

Note that you can optionally allow root to log in without a smartcard by adding
------------
auth       required     pam_nologin.so
------------

xscreeensaver only requires a PIN value, but prompts for a password.
This seems to be a bug in xscreensaver.


::::::::::::::
gdm
::::::::::::::
#%PAM-1.0
auth       required     pam_env.so
# If musclecard is "sufficient", then if this fails, fall back on the password
auth       sufficient   pam_musclecard.so service=system-auth debug
auth       required     pam_stack.so service=system-auth
# If you are sure, you may want to remove the next line
# It allows root to log in without a smartcard
auth       required     pam_nologin.so
account    required     pam_stack.so service=system-auth
password   required     pam_stack.so service=system-auth
session    required     pam_stack.so service=system-auth
session    optional     pam_console.so
::::::::::::::
gdm-autologin
::::::::::::::
#%PAM-1.0
auth       required     pam_env.so
auth       required     pam_nologin.so
auth       required     pam_permit.so
auth       required     pam_musclecard.so service=system-auth
account    required     pam_stack.so service=system-auth
password   required     pam_stack.so service=system-auth
session    required     pam_stack.so service=system-auth
session    optional     pam_console.so
::::::::::::::
login
::::::::::::::
#%PAM-1.0
#auth       required    pam_securetty.so
auth       required     /lib/security/pam_musclecard.so service=system-auth
#auth       required    pam_stack.so service=system-auth
#auth       required    pam_nologin.so
account    required     pam_stack.so service=system-auth
password   required     pam_stack.so service=system-auth
session    required     pam_stack.so service=system-auth
session    optional     pam_console.so
::::::::::::::
su
::::::::::::::
#%PAM-1.0
# If you remove the next line, then root will require a smartcard to do a 'su
# This might break things (cronjobs, admin scripts, etc.)
auth       sufficient   /lib/security/$ISA/pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth       sufficient   /lib/security/$ISA/pam_wheel.so trust use_uid
# Uncomment the following line to require a user to be in the "wheel" group.
#auth       required     /lib/security/$ISA/pam_wheel.so use_uid
#was
#  Normally we use the pam_stack, but in this case we use musclecard
#auth       required    /lib/security/$ISA/pam_stack.so service=system-auth
auth       required     /lib/security/pam_musclecard.so service=system-auth 
account    required     /lib/security/$ISA/pam_stack.so service=system-auth
password   required     /lib/security/$ISA/pam_stack.so service=system-auth
session    required     /lib/security/$ISA/pam_stack.so service=system-auth
session    optional     /lib/security/$ISA/pam_xauth.so
::::::::::::::
xscreensaver
::::::::::::::
#%PAM-1.0

# Red Hat says this is right for them, as of 7.3:
auth       required     pam_stack.so service=system-auth
auth       required     /lib/security/pam_musclecard.so service=system-auth  debug
#auth       required   pam_pwdb.so shadow nullok

