# Network Authentication

This section explains various Network Authentication protocols.

## OpenLDAP Server

LDAP is an acronym for Lightweight Directory Access Protocol, it is a simplified version of the X.500 protocol. The directory setup in this section will be used for authentication. Nevertheless, LDAP can be used in numerous ways: authentication, shared directory (for mail clients), address book, etc.

To describe LDAP quickly, all information is stored in a tree structure. With OpenLDAP you have freedom to determine the directory arborescence (the Directory Information Tree: the DIT) yourself. We will begin with a basic tree containing two nodes below the root:

- "People" node where your users will be stored

- "Groups" node where your groups will be stored

Before beginning, you should determine what the root of your LDAP directory will be. By default, your tree will be determined by your Fully Qualified Domain Name (FQDN). If your domain is example.com (which we will use in this example), your root node will be dc=example,dc=com.

### Installation

First, install the OpenLDAP server daemon slapd and ldap-utils, a package containing LDAP management utilities:

    sudo apt-get install slapd ldap-utils

By default slapd is configured with minimal options needed to run the slapd daemon.

The configuration example in the following sections will match the domain name of the server. For example, if the machine's Fully Qualified Domain Name (FQDN) is ldap.example.com, the default suffix will be dc=example,dc=com.

### Populating LDAP

OpenLDAP uses a separate directory which contains the cn=config Directory Information Tree (DIT). The cn=config DIT is used to dynamically configure the slapd daemon, allowing the modification of schema definitions, indexes, ACLs, etc without stopping the service.

The backend cn=config directory has only a minimal configuration and will need additional configuration options in order to populate the frontend directory. The frontend will be populated with a "classical" scheme that will be compatible with address book applications and with Unix Posix accounts. Posix accounts will allow authentication to various applications, such as web applications, email Mail Transfer Agent (MTA) applications, etc.

For external applications to authenticate using LDAP they will each need to be specifically configured to do so. Refer to the individual application documentation for details.

Remember to change dc=example,dc=com in the following examples to match your LDAP configuration.

First, some additional schema files need to be loaded. In a terminal enter:

    sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
    sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif
    sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif

Next, copy the following example LDIF file, naming it `backend.example.com.ldif`, somewhere on your system:

    # Load dynamic backend modules
    dn: cn=module,cn=config
    objectClass: olcModuleList
    cn: module
    olcModulepath: /usr/lib/ldap
    olcModuleload: back_hdb

    # Database settings
    dn: olcDatabase=hdb,cn=config
    objectClass: olcDatabaseConfig
    objectClass: olcHdbConfig
    olcDatabase: {1}hdb
    olcSuffix: dc=example,dc=com
    olcDbDirectory: /var/lib/ldap
    olcRootDN: cn=admin,dc=example,dc=com
    olcRootPW: secret
    olcDbConfig: set_cachesize 0 2097152 0
    olcDbConfig: set_lk_max_objects 1500
    olcDbConfig: set_lk_max_locks 1500
    olcDbConfig: set_lk_max_lockers 1500
    olcDbIndex: objectClass eq
    olcLastMod: TRUE
    olcDbCheckpoint: 512 30
    olcAccess: to attrs=userPassword by dn="cn=admin,dc=example,dc=com" write by anonymous auth by self write by * none
    olcAccess: to attrs=shadowLastChange by self write by * read
    olcAccess: to dn.base="" by * read
    olcAccess: to * by dn="cn=admin,dc=example,dc=com" write by * read

Change olcRootPW: secret to a password of your choosing.

Now add the LDIF to the directory:

    sudo ldapadd -Y EXTERNAL -H ldapi:/// -f backend.example.com.ldif

The frontend directory is now ready to be populated. Create a `frontend.example.com.ldif` with the following contents:

    # Create top-level object in domain
    dn: dc=example,dc=com
    objectClass: top
    objectClass: dcObject
    objectclass: organization
    o: Example Organization
    dc: Example
    description: LDAP Example

    # Admin user.
    dn: cn=admin,dc=example,dc=com
    objectClass: simpleSecurityObject
    objectClass: organizationalRole
    cn: admin
    description: LDAP administrator
    userPassword: secret

    dn: ou=people,dc=example,dc=com
    objectClass: organizationalUnit
    ou: people

    dn: ou=groups,dc=example,dc=com
    objectClass: organizationalUnit
    ou: groups

    dn: uid=john,ou=people,dc=example,dc=com
    objectClass: inetOrgPerson
    objectClass: posixAccount
    objectClass: shadowAccount
    uid: john
    sn: Doe
    givenName: John
    cn: John Doe
    displayName: John Doe
    uidNumber: 1000
    gidNumber: 10000
    userPassword: password
    gecos: John Doe
    loginShell: /bin/bash
    homeDirectory: /home/john
    shadowExpire: -1
    shadowFlag: 0
    shadowWarning: 7
    shadowMin: 8
    shadowMax: 999999
    shadowLastChange: 10877
    mail: john.doe@example.com
    postalCode: 31000
    l: Toulouse
    o: Example
    mobile: +33 (0)6 xx xx xx xx
    homePhone: +33 (0)5 xx xx xx xx
    title: System Administrator
    postalAddress:
    initials: JD

    dn: cn=example,ou=groups,dc=example,dc=com
    objectClass: posixGroup
    cn: example
    gidNumber: 10000

In this example the directory structure, a user, and a group have been setup. In other examples you might see the objectClass: top added in every entry, but that is the default behaviour so you do not have to add it explicitly.

Add the entries to the LDAP directory:

    sudo ldapadd -x -D cn=admin,dc=example,dc=com -W -f frontend.example.com.ldif

We can check that the content has been correctly added with the ldapsearch utility. Execute a search of the LDAP directory:

    ldapsearch -xLLL -b "dc=example,dc=com" uid=john sn givenName cn

    dn: uid=john,ou=people,dc=example,dc=com
    cn: John Doe
    sn: Doe
    givenName: John

Just a quick explanation:

- -x: will not use SASL authentication method, which is the default.

- -LLL: disable printing LDIF schema information.

### Further Configuration

The cn=config tree can be manipulated using the utilities in the ldap-utils package. For example:

- Use ldapsearch to view the tree, entering the admin password set during installation or reconfiguration:

      sudo ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn

      SASL/EXTERNAL authentication started
      SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
      SASL SSF: 0
      dn: cn=config

      dn: cn=module{0},cn=config

      dn: cn=schema,cn=config

      dn: cn={0}core,cn=schema,cn=config

      dn: cn={1}cosine,cn=schema,cn=config

      dn: cn={2}nis,cn=schema,cn=config

      dn: cn={3}inetorgperson,cn=schema,cn=config

      dn: olcDatabase={-1}frontend,cn=config

      dn: olcDatabase={0}config,cn=config

      dn: olcDatabase={1}hdb,cn=config

  The output above is the current configuration options for the cn=config backend database. Your output may be vary.

- As an example of modifying the cn=config tree, add another attribute to the index list using ldapmodify:

      sudo ldapmodify -Y EXTERNAL -H ldapi:///

      SASL/EXTERNAL authentication started
      SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
      SASL SSF: 0
      dn: olcDatabase={1}hdb,cn=config
      add: olcDbIndex
      olcDbIndex: uidNumber eq

      modifying entry "olcDatabase={1}hdb,cn=config"

  Once the modification has completed, press Ctrl+D to exit the utility.

- ldapmodify can also read the changes from a file. Copy and paste the following into a file named `uid_index.ldif`:

      dn: olcDatabase={1}hdb,cn=config
      add: olcDbIndex
      olcDbIndex: uid eq,pres,sub

  Then execute ldapmodify:

      sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f uid_index.ldif

      SASL/EXTERNAL authentication started
      SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
      SASL SSF: 0
      modifying entry "olcDatabase={1}hdb,cn=config"

  The file method is very useful for large changes.

- Adding additional schemas to slapd requires the schema to be converted to LDIF format. The `/etc/ldap/schema` directory contains some schema files already converted to LDIF format as demonstrated in the previous section. Fortunately, the slapd program can be used to automate the conversion. The following example will add the dyngoup.schema:

- First, create a conversion `schema_convert.conf` file containing the following lines:

      include /etc/ldap/schema/core.schema
      include /etc/ldap/schema/collective.schema
      include /etc/ldap/schema/corba.schema
      include /etc/ldap/schema/cosine.schema
      include /etc/ldap/schema/duaconf.schema
      include /etc/ldap/schema/dyngroup.schema
      include /etc/ldap/schema/inetorgperson.schema
      include /etc/ldap/schema/java.schema
      include /etc/ldap/schema/misc.schema
      include /etc/ldap/schema/nis.schema
      include /etc/ldap/schema/openldap.schema
      include /etc/ldap/schema/ppolicy.schema

- Next, create a temporary directory to hold the output:

      mkdir /tmp/ldif_output

- Now using slapcat convert the schema files to LDIF:

      slapcat -f schema_convert.conf -F /tmp/ldif_output -n0 -s "cn={5}dyngroup,cn=schema,cn=config" > /tmp/cn=dyngroup.ldif

  Adjust the configuration file name and temporary directory names if yours are different. Also, it may be worthwhile to keep the `ldif_output` directory around in case you want to add additional schemas in the future.

- Edit the `/tmp/cn\=dyngroup.ldif` file, changing the following attributes:

      dn: cn=dyngroup,cn=schema,cn=config
      ...
      cn: dyngroup

  And remove the following lines from the bottom of the file:

      structuralObjectClass: olcSchemaConfig
      entryUUID: 10dae0ea-0760-102d-80d3-f9366b7f7757
      creatorsName: cn=config
      createTimestamp: 20080826021140Z
      entryCSN: 20080826021140.791425Z#000000#000#000000
      modifiersName: cn=config
      modifyTimestamp: 20080826021140Z

  The attribute values will vary, just be sure the attributes are removed.

- Finally, using the ldapadd utility, add the new schema to the directory:

      sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp/cn\=dyngroup.ldif

There should now be a dn: cn={4}dyngroup,cn=schema,cn=config entry in the cn=config tree.

### LDAP Replication

LDAP often quickly becomes a highly critical service to the network. Multiple systems will come to depend on LDAP for authentication, authorization, configuration, etc. It is a good idea to setup a redundant system through replication.

Replication is achieved using the Syncrepl engine. Syncrepl allows the changes to be synced using a consumer, provider model. A provider sends directory changes to consumers.

#### Provider Configuration

The following is an example of a Single-Master configuration. In this configuration one OpenLDAP server is configured as a provider and another as a consumer.

- First, configure the provider server. Copy the following to a file named `provider_sync.ldif`:

      # Add indexes to the frontend db.
      dn: olcDatabase={1}hdb,cn=config
      changetype: modify
      add: olcDbIndex
      olcDbIndex: entryCSN eq
      -
      add: olcDbIndex
      olcDbIndex: entryUUID eq

      #Load the syncprov and accesslog modules.
      dn: cn=module{0},cn=config
      changetype: modify
      add: olcModuleLoad
      olcModuleLoad: syncprov
      -
      add: olcModuleLoad
      olcModuleLoad: accesslog

      # Accesslog database definitions
      dn: olcDatabase={2}hdb,cn=config
      objectClass: olcDatabaseConfig
      objectClass: olcHdbConfig
      olcDatabase: {2}hdb
      olcDbDirectory: /var/lib/ldap/accesslog
      olcSuffix: cn=accesslog
      olcRootDN: cn=admin,dc=example,dc=com
      olcDbIndex: default eq
      olcDbIndex: entryCSN,objectClass,reqEnd,reqResult,reqStart

      # Accesslog db syncprov.
      dn: olcOverlay=syncprov,olcDatabase={2}hdb,cn=config
      changetype: add
      objectClass: olcOverlayConfig
      objectClass: olcSyncProvConfig
      olcOverlay: syncprov
      olcSpNoPresent: TRUE
      olcSpReloadHint: TRUE

      # syncrepl Provider for primary db
      dn: olcOverlay=syncprov,olcDatabase={1}hdb,cn=config
      changetype: add
      objectClass: olcOverlayConfig
      objectClass: olcSyncProvConfig
      olcOverlay: syncprov
      olcSpNoPresent: TRUE

      # accesslog overlay definitions for primary db
      dn: olcOverlay=accesslog,olcDatabase={1}hdb,cn=config
      objectClass: olcOverlayConfig
      objectClass: olcAccessLogConfig
      olcOverlay: accesslog
      olcAccessLogDB: cn=accesslog
      olcAccessLogOps: writes
      olcAccessLogSuccess: TRUE
      # scan the accesslog DB every day, and purge entries older than 7 days
      olcAccessLogPurge: 07+00:00 01+00:00

- The AppArmor profile for slapd will need to be adjusted for the accesslog database location. Edit `/etc/apparmor.d/usr.sbin.slapd` adding:

        /var/lib/ldap/accesslog/ r,
        /var/lib/ldap/accesslog/** rwk,

  Then create the directory, reload the apparmor profile, and copy the `DB_CONFIG` file:

      sudo -u openldap mkdir /var/lib/ldap/accesslog
      sudo -u openldap cp /var/lib/ldap/DB_CONFIG /var/lib/ldap/accesslog/
      sudo /etc/init.d/apparmor reload

  Using the -u openldap option with the sudo commands above removes the need to adjust permissions for the new directory later.

- Edit the file and change the olcRootDN to match your directory:

      olcRootDN: cn=admin,dc=example,dc=com

- Next, add the LDIF file using the ldapadd utility:

      sudo ldapadd -Y EXTERNAL -H ldapi:/// -f provider_sync.ldif

- Restart slapd:

      sudo /etc/init.d/slapd restart

The Provider server is now configured, and it is time to configure a Consumer server.

#### Consumer Configuration

- On the Consumer server configure it the same as the Provider except for the Syncrepl configuration steps.

  Add the additional schema files:

      sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
      sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif
      sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif

  Also, create, or copy from the provider server, the `backend.example.com.ldif`

      # Load dynamic backend modules
      dn: cn=module,cn=config
      objectClass: olcModuleList
      cn: module
      olcModulepath: /usr/lib/ldap
      olcModuleload: back_hdb

      # Database settings
      dn: olcDatabase=hdb,cn=config
      objectClass: olcDatabaseConfig
      objectClass: olcHdbConfig
      olcDatabase: {1}hdb
      olcSuffix: dc=example,dc=com
      olcDbDirectory: /var/lib/ldap
      olcRootDN: cn=admin,dc=example,dc=com
      olcRootPW: secret
      olcDbConfig: set_cachesize 0 2097152 0
      olcDbConfig: set_lk_max_objects 1500
      olcDbConfig: set_lk_max_locks 1500
      olcDbConfig: set_lk_max_lockers 1500
      olcDbIndex: objectClass eq
      olcLastMod: TRUE
      olcDbCheckpoint: 512 30
      olcAccess: to attrs=userPassword by dn="cn=admin,dc=example,dc=com" write by anonymous auth by self write by * none
      olcAccess: to attrs=shadowLastChange by self write by * read
      olcAccess: to dn.base="" by * read
      olcAccess: to * by dn="cn=admin,dc=example,dc=com" write by * read

  And add the LDIF by entering:

      sudo ldapadd -Y EXTERNAL -H ldapi:/// -f backend.example.com.ldif

- Do the same with the `frontend.example.com.ldif` file listed above, and add it:

      sudo ldapadd -x -D cn=admin,dc=example,dc=com -W -f frontend.example.com.ldif

  The two severs should now have the same configuration except for the Syncrepl options.

- Now create a file named `consumer_sync.ldif` containing:

      #Load the syncprov module.
      dn: cn=module{0},cn=config
      changetype: modify
      add: olcModuleLoad
      olcModuleLoad: syncprov

      # syncrepl specific indices
      dn: olcDatabase={1}hdb,cn=config
      changetype: modify
      add: olcDbIndex
      olcDbIndex: entryUUID eq
      -
      add: olcSyncRepl
      olcSyncRepl: rid=0 provider=ldap://ldap01.example.com bindmethod=simple binddn="cn=admin,dc=example,dc=com"
       credentials=secret searchbase="dc=example,dc=com" logbase="cn=accesslog"
       logfilter="(&(objectClass=auditWriteObject)(reqResult=0))" schemachecking=on
       type=refreshAndPersist retry="60 +" syncdata=accesslog
      -
      add: olcUpdateRef
      olcUpdateRef: ldap://ldap01.example.com

  You will probably want to change the following attributes:

  - ldap01.example.com to your server's hostname.

  - binddn

  - credentials

  - searchbase

  - olcUpdateRef:

- Add the LDIF file to the configuration tree:

      sudo ldapadd -c -Y EXTERNAL -H ldapi:/// -f consumer_sync.ldif

The frontend database should now sync between servers. You can add additional servers using the steps above as the need arises.

The slapd daemon will send log information to `/var/log/syslog` by default. So if all does not go well check there for errors and other troubleshooting information. Also, be sure that each server knows it's Fully Qualified Domain Name (FQDN). This is configured in `/etc/hosts` with a line similar to:

    127.0.0.1	ldap01.example.com ldap01

.

### Setting up ACL

Authentication requires access to the password field, that should be not accessible by default. Also, in order for users to change their own password, using `passwd` or other utilities, shadowLastChange needs to be accessible once a user has authenticated.

To view the Access Control List (ACL), use the ldapsearch utility:

    ldapsearch -xLLL -b cn=config -D cn=admin,cn=config -W olcDatabase=hdb olcAccess

    Enter LDAP Password:
    dn: olcDatabase={1}hdb,cn=config
    olcAccess: {0}to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=exampl
     e,dc=com" write by anonymous auth by self write by * none
    olcAccess: {1}to dn.base="" by * read
    olcAccess: {2}to * by dn="cn=admin,dc=example,dc=com" write by * read

### TLS and SSL

When authenticating to an OpenLDAP server it is best to do so using an encrypted session. This can be accomplished using Transport Layer Security (TLS) and/or Secure Sockets Layer (SSL).

The first step in the process is to obtain or create a certificate. Because slapd is compiled using the gnutls library, the certtool utility will be used to create certificates.

- First, install gnutls-bin by entering the following in a terminal:

      sudo apt-get install gnutls-bin

- Next, create a private key for the Certificate Authority (CA):

      sudo sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem"

- Create a `/etc/ssl/ca.info` details file to self-sign the CA certificate containing:

      cn = Example Company
      ca
      cert_signing_key

- Now create the self-signed CA certificate:

      sudo certtool --generate-self-signed --load-privkey /etc/ssl/private/cakey.pem \
       --template  /etc/ssl/ca.info --outfile /etc/ssl/certs/cacert.pem

- Make a private key for the server:

      sudo sh -c "certtool --generate-privkey > /etc/ssl/private/ldap01_slapd_key.pem"

  Replace ldap01 in the filename with your server's hostname. Naming the certificate and key for the host and service that will be using them will help keep filenames and paths straight.

- To sign the server's certificate with the CA, create the `/etc/ssl/ldap01.info` info file containing:

      organization = Example Company
      cn = ldap01.example.com
      tls_www_server
      encryption_key
      signing_key

- Create the server's certificate:

      sudo certtool --generate-certificate --load-privkey /etc/ssl/private/x01-test_slapd_key.pem \
       --load-ca-certificate /etc/ssl/certs/cacert.pem --load-ca-privkey /etc/ssl/private/cakey.pem \
       --template /etc/ssl/x01-test.info --outfile /etc/ssl/certs/x01-test_slapd_cert.pem

Once you have a certificate, key, and CA cert installed, use ldapmodify to add the new configuration options:

    sudo ldapmodify -Y EXTERNAL -H ldapi:///

    Enter LDAP Password:
    dn: cn=config
    add: olcTLSCACertificateFile
    olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
    -
    add: olcTLSCertificateFile
    olcTLSCertificateFile: /etc/ssl/certs/ldap01_slapd_cert.pem
    -
    add: olcTLSCertificateKeyFile
    olcTLSCertificateKeyFile: /etc/ssl/private/ldap01_slapd_key.pem

    modifying entry "cn=config"

Adjust the `ldap01_slapd_cert.pem`, `ldap01_slapd_key.pem`, and `cacert.pem` names if yours are different.

Next, edit `/etc/default/slapd` uncomment the SLAPD_SERVICES option:

    SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"

Now the openldap user needs access to the certificate:

    sudo adduser openldap ssl-cert
    sudo chgrp ssl-cert /etc/ssl/private/ldap01_slapd_key.pem
    sudo chmod g+r /etc/ssl/private/ldap01_slapd_key.pem

If the `/etc/ssl/private` and `/etc/ssl/private/server.key` have different permissions, adjust the commands appropriately.

Finally, restart slapd:

    sudo /etc/init.d/slapd restart

The slapd daemon should now be listening for LDAPS connections and be able to use STARTTLS during authentication.

If you run into troubles with the server not starting, check the /var/log/syslog. If you see errors like main: TLS init def ctx failed: -1, it is likely there is a configuration problem. Check that the certificate is signed by the authority from in the files configured, and that the ssl-cert group has read permissions on the private key.

#### TLS Replication

If you have setup Syncrepl between servers, it is prudent to encrypt the replication traffic using Transport Layer Security (TLS). For details on setting up replication see .

Assuming you have followed the above instructions and created a CA certificate and server certificate on the Provider server. Follow the following instructions to create a certificate and key for the Consumer server.

- Create a new key for the Consumer server:

      mkdir ldap02-ssl
      cd ldap02-ssl
      certtool --generate-privkey > ldap02_slapd_key.pem

  Creating a new directory is not strictly necessary, but it will help keep things organized and make it easier to copy the files to the Consumer server.

- Next, create an info file, `ldap02.info` for the Consumer server, changing the attributes to match your locality and server:

      country = US
      state = North Carolina
      locality = Winston-Salem
      organization = Example Company
      cn = ldap02.salem.edu
      tls_www_client
      encryption_key
      signing_key

- Create the certificate:

      sudo certtool --generate-certificate --load-privkey ldap02_slapd_key.pem \
       --load-ca-certificate /etc/ssl/certs/cacert.pem --load-ca-privkey /etc/ssl/private/cakey.pem \
       --template ldap02.info --outfile ldap02_slapd_cert.pem

- Copy the `cacert.pem` to the dicretory:

      cp /etc/ssl/certs/cacert.pem .

- The only thing left is to copy the `ldap02-ssl` directory to the Consumer server, then copy `ldap02_slapd_cert.pem` and `cacert.pem` to `/etc/ssl/certs`, and copy `ldap02_slapd_key.pem` to `/etc/ssl/private`.

- Once the files are in place adjust the cn=config tree by entering:

      sudo ldapmodify -Y EXTERNAL -H ldapi:///

      Enter LDAP Password:
      dn: cn=config
      add: olcTLSCACertificateFile
      olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
      -
      add: olcTLSCertificateFile
      olcTLSCertificateFile: /etc/ssl/certs/ldap02_slapd_cert.pem
      -
      add: olcTLSCertificateKeyFile
      olcTLSCertificateKeyFile: /etc/ssl/private/ldap02_slapd_key.pem

      modifying entry "cn=config"

- As with the Provider you can now edit `/etc/default/slapd` and add the ldaps:/// parameter to the SLAPD_SERVICES option.

Now that TLS has been setup on each server, once again modify the Consumer server's cn=config tree by entering the following in a terminal:

    sudo ldapmodify -Y EXTERNAL -H ldapi:///

    SASL/EXTERNAL authentication started
    SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
    SASL SSF: 0

    dn: olcDatabase={1}hdb,cn=config
    replace: olcSyncrepl
    olcSyncrepl: {0}rid=0 provider=ldap://ldap01.example.com bindmethod=simple binddn="cn=ad
     min,dc=example,dc=com" credentials=secret searchbase="dc=example,dc=com" logbas
     e="cn=accesslog" logfilter="(&(objectClass=auditWriteObject)(reqResult=0))" s
     chemachecking=on type=refreshAndPersist retry="60 +" syncdata=accesslog starttls=yes

    modifying entry "olcDatabase={1}hdb,cn=config"

If the LDAP server hostname does not match the Fully Qualified Domain Name (FQDN) in the certificate, you may have to edit `/etc/ldap/ldap.conf` and add the following TLS options:

    TLS_CERT /etc/ssl/certs/ldap02_slapd_cert.pem
    TLS_KEY /etc/ssl/private/ldap02_slapd_key.pem
    TLS_CACERT /etc/ssl/certs/cacert.pem

Finally, restart slapd on each of the servers:

    sudo /etc/init.d/slapd restart

### LDAP Authentication

Once you have a working LDAP server, the auth-client-config and libnss-ldap packages take the pain out of configuring an Ubuntu client to authenticate using LDAP. To install the packages from, a terminal prompt enter:

    sudo apt-get install libnss-ldap

During the install a menu dialog will ask you connection details about your LDAP server.

If you make a mistake when entering your information you can execute the dialog again using:

    sudo dpkg-reconfigure ldap-auth-config

The results of the dialog can be seen in `/etc/ldap.conf`. If your server requires options not covered in the menu edit this file accordingly.

Now that libnss-ldap is configured enable the auth-client-config LDAP profile by entering:

    sudo auth-client-config -t nss -p lac_ldap

- -t: only modifies `/etc/nsswitch.conf`.

- -p: name of the profile to enable, disable, etc.

- lac_ldap: the auth-client-config profile that is part of the ldap-auth-config package.

Using the pam-auth-update utility, configure the system to use LDAP for authentication:

    sudo pam-auth-update

From the pam-auth-update menu, choose LDAP and any other authentication mechanisms you need.

You should now be able to login using user credentials stored in the LDAP directory.

If you are going to use LDAP to store Samba users you will need to configure the server to authenticate using LDAP. See for details.

### User and Group Management

The ldap-utils package comes with multiple utilities to manage the directory, but the long string of options needed, can make them a burden to use. The ldapscripts package contains configurable scripts to easily manage LDAP users and groups.

To install the package, from a terminal enter:

    sudo apt-get install ldapscripts

Next, edit the config file `/etc/ldapscripts/ldapscripts.conf` uncommenting and changing the following to match your environment:

    SERVER=localhost
    BINDDN='cn=admin,dc=example,dc=com'
    BINDPWDFILE="/etc/ldapscripts/ldapscripts.passwd"
    SUFFIX='dc=example,dc=com'
    GSUFFIX='ou=Groups'
    USUFFIX='ou=People'
    MSUFFIX='ou=Computers'
    GIDSTART=10000
    UIDSTART=10000
    MIDSTART=10000

Now, create the `ldapscripts.passwd` file to allow authenticated access to the directory:

    sudo sh -c "echo -n 'secret' > /etc/ldapscripts/ldapscripts.passwd"
    sudo chmod 400 /etc/ldapscripts/ldapscripts.passwd

Replace secret with the actual password for your LDAP admin user.

The ldapscripts are now ready to help manage your directory. The following are some examples of how to use the scripts:

- Create a new user:

      sudo ldapadduser george example

  This will create a user with uid george and set the user's primary group (gid) to example

- Change a user's password:

      sudo ldapsetpasswd george
      Changing password for user uid=george,ou=People,dc=example,dc=com
      New Password:
      New Password (verify):

- Delete a user:

      sudo ldapdeleteuser george

- Add a group:

      sudo ldapaddgroup qa

- Delete a group:

      sudo ldapdeletegroup qa

- Add a user to a group:

      sudo ldapaddusertogroup george qa

  You should now see a memberUid attribute for the qa group with a value of george.

- Remove a user from a group:

      sudo ldapdeleteuserfromgroup george qa

  The memberUid attribute should now be removed from the qa group.

- The ldapmodifyuser script allows you to add, remove, or replace a user's attributes. The script uses the same syntax as the ldapmodify utility. For example:

      sudo ldapmodifyuser george
      # About to modify the following entry :
      dn: uid=george,ou=People,dc=example,dc=com
      objectClass: account
      objectClass: posixAccount
      cn: george
      uid: george
      uidNumber: 1001
      gidNumber: 1001
      homeDirectory: /home/george
      loginShell: /bin/bash
      gecos: george
      description: User account
      userPassword:: e1NTSEF9eXFsTFcyWlhwWkF1eGUybVdFWHZKRzJVMjFTSG9vcHk=

      # Enter your modifications here, end with CTRL-D.
      dn: uid=george,ou=People,dc=example,dc=com
      replace: gecos
      gecos: George Carlin

  The user's gecos should now be George Carlin.

- Another great feature of ldapscripts, is the template system. Templates allow you to customize the attributes of user, group, and machine objectes. For example, to enable the user template edit `/etc/ldapscripts/ldapscripts.conf` changing:

      UTEMPLATE="/etc/ldapscripts/ldapadduser.template"

  There are sample templates in the `/etc/ldapscripts` directory. Copy or rename the `ldapadduser.template.sample` file to `/etc/ldapscripts/ldapadduser.template`:

      sudo cp /etc/ldapscripts/ldapadduser.template.sample /etc/ldapscripts/ldapadduser.template

  Edit the new template to add the desired attributes. The following will create new user's as with an objectClass of inetOrgPerson:

      dn: uid=<user>,<usuffix>,<suffix>
      objectClass: inetOrgPerson
      objectClass: posixAccount
      cn: <user>
      sn: <ask>
      uid: <user>
      uidNumber: <uid>
      gidNumber: <gid>
      homeDirectory: <home>
      loginShell: <shell>
      gecos: <user>
      description: User account
      title: Employee

  Notice the <ask> option used for the cn value. Using <ask> will configure ldapadduser to prompt you for the attribute value during user creation.

There are more useful scripts in the package, to see a full list enter: `dpkg -L ldapscripts | grep bin`

### Resources

- The OpenLDAP Ubuntu Wiki page has more details.

- For more information see OpenLDAP Home Page

- Though starting to show it's age, a great source for in depth LDAP information is O'Reilly's LDAP System Administration

- Packt's Mastering OpenLDAP is a great reference covering newer versions of OpenLDAP.

- For more information on auth-client-config see the man page: `man auth-client-config`.

- For more details regarding the ldapscripts package see the man pages: `man ldapscripts`, `man ldapadduser`, `man ldapaddgroup`, etc.

## Samba and LDAP

This section covers configuring Samba to use LDAP for user, group, and machine account information and authentication. The assumption is, you already have a working OpenLDAP directory installed and the server is configured to use it for authentication. See and for details on setting up OpenLDAP. For more information on installing and configuring Samba see .

### Installation

There are three packages needed when integrating Samba with LDAP. samba, samba-doc, and smbldap-tools packages . To install the packages, from a terminal enter:

    sudo apt-get install samba samba-doc smbldap-tools

Strictly speaking the smbldap-tools package isn't needed, but unless you have another package or custom scripts, a method of managing users, groups, and computer accounts is needed.

### OpenLDAP Configuration

In order for Samba to use OpenLDAP as a passdb backend, the user objects in the directory will need additional attributes. This section assumes you want Samba to be configured as a Windows NT domain controller, and will add the necessary LDAP objects and attributes.

- The Samba attributes are defined in the `samba.schema` file which is part of the samba-doc package. The schema file needs to be unzipped and copied to `/etc/ldap/schema`. From a terminal prompt enter:

      sudo cp /usr/share/doc/samba-doc/examples/LDAP/samba.schema.gz /etc/ldap/schema/
      sudo gzip -d /etc/ldap/schema/samba.schema.gz

- The samba schema needs to be added to the cn=config tree. The procedure to add a new schema to slapd is also detailed in .

- First, create a configuration file named `schema_convert.conf`, or a similar descriptive name, containing the following lines:

      include /etc/ldap/schema/core.schema
      include /etc/ldap/schema/collective.schema
      include /etc/ldap/schema/corba.schema
      include /etc/ldap/schema/cosine.schema
      include /etc/ldap/schema/duaconf.schema
      include /etc/ldap/schema/dyngroup.schema
      include /etc/ldap/schema/inetorgperson.schema
      include /etc/ldap/schema/java.schema
      include /etc/ldap/schema/misc.schema
      include /etc/ldap/schema/nis.schema
      include /etc/ldap/schema/openldap.schema
      include /etc/ldap/schema/ppolicy.schema
      include /etc/ldap/schema/samba.schema

- Next, create a temporary directory to hold the output:

      mkdir /tmp/ldif_output

- Now use slapcat to convert the schema files:

      slapcat -f schema_convert.conf -F /tmp/ldif_output -n0 -s "cn={12}samba,cn=schema,cn=config" > /tmp/cn=samba.ldif

  Change the above file and path names to match your own if they are different.

- Edit the generated `/tmp/cn\=samba.ldif` file, changing the following attributes:

      dn: cn=samba,cn=schema,cn=config
      ...
      cn: samba

  And remove the following lines from the bottom of the file:

      structuralObjectClass: olcSchemaConfig
      entryUUID: b53b75ca-083f-102d-9fff-2f64fd123c95
      creatorsName: cn=config
      createTimestamp: 20080827045234Z
      entryCSN: 20080827045234.341425Z#000000#000#000000
      modifiersName: cn=config
      modifyTimestamp: 20080827045234Z

  The attribute values will vary, just be sure the attributes are removed.

- Finally, using the ldapadd utility, add the new schema to the directory:

      ldapadd -x -D cn=admin,cn=config -W -f /tmp/cn\=samba.ldif

There should now be a dn: cn={X}misc,cn=schema,cn=config, where "X" is the next sequential schema, entry in the cn=config tree.

- Copy and paste the following into a file named `samba_indexes.ldif`:

      dn: olcDatabase={1}hdb,cn=config
      changetype: modify
      add: olcDbIndex
      olcDbIndex: uidNumber eq
      olcDbIndex: gidNumber eq
      olcDbIndex: loginShell eq
      olcDbIndex: uid eq,pres,sub
      olcDbIndex: memberUid eq,pres,sub
      olcDbIndex: uniqueMember eq,pres
      olcDbIndex: sambaSID eq
      olcDbIndex: sambaPrimaryGroupSID eq
      olcDbIndex: sambaGroupType eq
      olcDbIndex: sambaSIDList eq
      olcDbIndex: sambaDomainName eq
      olcDbIndex: default sub

  Using the ldapmodify utility load the new indexes:

      ldapmodify -x -D cn=admin,cn=config -W -f samba_indexes.ldif

  If all went well you should see the new indexes using ldapsearch:

      ldapsearch -xLLL -D cn=admin,cn=config -x -b cn=config -W olcDatabase={1}hdb

- Next, configure the smbldap-tools package to match your environment. The package comes with a configuration script that will ask questions about the needed options. To run the script enter:

      sudo gzip -d /usr/share/doc/smbldap-tools/configure.pl.gz
      sudo perl /usr/share/doc/smbldap-tools/configure.pl

  Once you have answered the questions, there should be `/etc/smbldap-tools/smbldap.conf` and `/etc/smbldap-tools/smbldap_bind.conf` files. These files are generated by the configure script, so if you made any mistakes while executing the script it may be simpler to edit the file appropriately.

- The smbldap-populate script will add the necessary users, groups, and LDAP objects required for Samba. It is a good idea to make a backup LDAP Data Interchange Format (LDIF) file with slapcat before executing the command:

      sudo slapcat -l backup.ldif

- Once you have a current backup execute smbldap-populate by entering:

      sudo smbldap-populate

  You can create an LDIF file containing the new Samba objects by executing `sudo smbldap-populate -e samba.ldif`. This allows you to look over the changes making sure everything is correct.

Your LDAP directory now has the necessary domain information to authenticate Samba users.

### Samba Configuration

There a multiple ways to configure Samba for details on some common configurations see . To configure Samba to use LDAP, edit the main Samba configuration file `/etc/samba/smb.conf` commenting the passdb backend option and adding the following:

    #   passdb backend = tdbsam

    # LDAP Settings
       passdb backend = ldapsam:ldap://hostname
       ldap suffix = dc=example,dc=com
       ldap user suffix = ou=People
       ldap group suffix = ou=Groups
       ldap machine suffix = ou=Computers
       ldap idmap suffix = ou=Idmap
       ldap admin dn = cn=admin,dc=example,dc=com
       ldap ssl = start tls
       ldap passwd sync = yes
    ...
       add machine script = sudo /usr/sbin/smbldap-useradd -t 0 -w "%u"

Restart samba to enable the new settings:

    sudo /etc/init.d/samba restart

Now Samba needs to know the LDAP admin password. From a terminal prompt enter:

    sudo smbpasswd -w secret

Replacing secret with your LDAP admin password.

If you currently have users in LDAP, and you want them to authenticate using Samba, they will need some Samba attributes defined in the `samba.schema` file. Add the Samba attributes to existing users using the smbpasswd utility, replacing username with an actual user:

    sudo smbpasswd -a username

You will then be asked to enter the user's password.

To add new user, group, and machine accounts use the utilities from the smbldap-tools package. Here are some examples:

- To add a new user to LDAP with Samba attributes enter the following, replacing username with an actual username:

      sudo smbldap-useradd -a -P username

  The -a option adds the Samba attributes, and the -P options calls the smbldap-passwd utility after the user is created allowing you to enter a password for the user.

- To remove a user from the directory enter:

      sudo smbldap-userdel username

  The smbldap-userdel utility also has a -r option to remove the user's home directory.

- Use smbldap-groupadd to add a group, replacing groupname with an appropriate group:

      sudo smbldap-groupadd -a groupname

  Similar to smbldap-useradd, the -a adds the Samba attributes.

- To add a user to a group use smbldap-groupmod:

      sudo smbldap-groupmod -m username groupname

  Be sure to replace username with a real user. Also, the -m option can add more than one user at a time by listing them in comma separated format.

- smbldap-groupmod can also be used to remove a user from a group:

      sudo smbldap-groupmod -x username groupname

- Additionally, the smbldap-useradd utility can add Samba machine accounts:

      sudo smbldap-useradd -t 0 -w username

  Replace username with the name of the workstation. The -t 0 option creates the machine account without a delay, while the -w option specifies the user as a machine account. Also, note the add machine script option in `/etc/samba/smb.conf` was changed to use smbldap-useradd.

There are more useful utilities and options in the smbldap-tools package. The man page for each utility provides more details.

### Resources

- There are multiple places where LDAP and Samba is documented in the Samba HOWTO Collection.

- Specifically see the passdb section.

- Another good site is Samba OpenLDAP HOWTO.

- Again, for more information on smbldap-tools see the man pages: `man smbldap-useradd`, `man smbldap-groupadd`, `man smbldap-populate`, etc.

- Also, there is a list of Ubuntu wiki articles with more information.

## Kerberos

Kerberos is a network authentication system based on the principal of a trusted third party. The other two parties being the user and the service the user wishes to authenticate to. Not all services and applications can use Kerberos, but for those that can, it brings the network environment one step closer to being Single Sign On (SSO).

This section covers installation and configuration of a Kerberos server, and some example client configurations.

### Overview

If you are new to Kerberos there are a few terms that are good to understand before setting up a Kerberos server. Most of the terms will relate to things you may be familiar with in other environments:

- Principal: any users, computers, and services provided by servers need to be defined as Kerberos Principals.

- Instances: are used for service principals and special administrative principals.

- Realms: the unique realm of control provided by the Kerberos installation. Usually the DNS domain converted to uppercase (EXAMPLE.COM).

- Key Distribution Center: (KDC) consist of three parts, a database of all principals, the authentication server, and the ticket granting server. For each realm there must be at least one KDC.

- Ticket Granting Ticket: issued by the Authentication Server (AS), the Ticket Granting Ticket (TGT) is encrypted in the user's password which is known only to the user and the KDC.

- Ticket Granting Server: (TGS) issues service tickets to clients upon request.

- Tickets: confirm the identity of the two principals. One principal being a user and the other a service requested by the user. Tickets establish an encryption key used for secure communication during the authenticated session.

- Keytab Files: are files extracted from the KDC principal database and contain the encryption key for a service or host.

To put the pieces together, a Realm has at least one KDC, preferably two for redundancy, which contains a database of Principals. When a user principal logs into a workstation, configured for Kerberos authentication, the KDC issues a Ticket Granting Ticket (TGT). If the user supplied credentials match, the user is authenticated and can then request tickets for Kerberized services from the Ticket Granting Server (TGS). The service tickets allow the user to authenticate to the service without entering another username and password.

### Kerberos Server

#### Installation

Before installing the Kerberos server a properly configured DNS server is needed for your domain. Since the Kerberos Realm by convention matches the domain name, this section uses the example.com domain configured in .

Also, Kerberos is a time sensitive protocol. So if the local system time between a client machine and the server differs by more than five minutes (by default), the workstation will not be able to authenticate. To correct the problem all hosts should have their time synchronized using the Network Time Protocol (NTP). For details on setting up NTP see .

The first step in installing a Kerberos Realm is to install the krb5-kdc and krb5-admin-server packages. From a terminal enter:

    sudo apt-get install krb5-kdc krb5-admin-server

You will be asked at the end of the install to supply a name for the Kerberos and Admin servers, which may or may not be the same server, for the realm.

Next, create the new realm with the kdb5_newrealm utility:

    sudo krb5_newrealm

#### Configuration

The questions asked during installation are used to configure the `/etc/krb5.conf` file. If you need to adjust the Key Distribution Center (KDC) settings simply edit the file and restart the krb5-kdc daemon.

- Now that the KDC running an admin user is needed. It is recommended to use a different username from your everyday username. Using the kadmin.local utility in a terminal prompt enter:

      sudo kadmin.local
      Authenticating as principal root/admin@EXAMPLE.COM with password.
      kadmin.local: addprinc steve/admin
      WARNING: no policy specified for steve/admin@EXAMPLE.COM; defaulting to no policy
      Enter password for principal "steve/admin@EXAMPLE.COM":
      Re-enter password for principal "steve/admin@EXAMPLE.COM":
      Principal "steve/admin@EXAMPLE.COM" created.
      kadmin.local: quit

  In the above example steve is the Principal, /admin is an Instance, and @EXAMPLE.COM signifies the realm. The "every day" Principal would be steve@EXAMPLE.COM, and should have only normal user rights.

  Replace EXAMPLE.COM and steve with your Realm and admin username.

- Next, the new admin user needs to have the appropriate Access Control List (ACL) permissions. The permissions are configured in the `/etc/krb5kdc/kadm5.acl` file:

      steve/admin@EXAMPLE.COM        *

  This entry grants steve/admin the ability to perform any operation on all principals in the realm.

- Now restart the krb5-admin-server for the new ACL to take affect:

      sudo /etc/init.d/krb5-admin-server restart

- The new user principal can be tested using the kinit utility:

      kinit steve/admin
      steve/admin@EXAMPLE.COM's Password:

  After entering the password, use the klist utility to view information about the Ticket Granting Ticket (TGT):

      klist
      Credentials cache: FILE:/tmp/krb5cc_1000
              Principal: steve/admin@EXAMPLE.COM

        Issued           Expires          Principal
      Jul 13 17:53:34  Jul 14 03:53:34  krbtgt/EXAMPLE.COM@EXAMPLE.COM

  You may need to add an entry into the `/etc/hosts` for the KDC. For example:

      192.168.0.1   kdc01.example.com       kdc01

  Replacing 192.168.0.1 with the IP address of your KDC.

- In order for clients to determine the KDC for the Realm some DNS SRV records are needed. Add the following to `/etc/named/db.example.com`:

      _kerberos._udp.EXAMPLE.COM.     IN SRV 1  0 88  kdc01.example.com.
      _kerberos._tcp.EXAMPLE.COM.     IN SRV 1  0 88  kdc01.example.com.
      _kerberos._udp.EXAMPLE.COM.     IN SRV 10 0 88  kdc02.example.com.
      _kerberos._tcp.EXAMPLE.COM.     IN SRV 10 0 88  kdc02.example.com.
      _kerberos-adm._tcp.EXAMPLE.COM. IN SRV 1  0 749 kdc01.example.com.
      _kpasswd._udp.EXAMPLE.COM.      IN SRV 1  0 464 kdc01.example.com.

  Replace EXAMPLE.COM, kdc01, and kdc02 with your domain name, primary KDC, and secondary KDC.

  See for detailed instructions on setting up DNS.

Your new Kerberos Realm is now ready to authenticate clients.

### Secondary KDC

Once you have one Key Distribution Center (KDC) on your network, it is good practice to have a Secondary KDC in case the primary becomes unavailable.

- First, install the packages, and when asked for the Kerberos and Admin server names enter the name of the Primary KDC:

      sudo apt-get install krb5-kdc krb5-admin-server

- Once you have the packages installed, create the Secondary KDC's host principal. From a terminal prompt, enter:

      kadmin -q "addprinc -randkey host/kdc02.example.com"

  After, issuing any kadmin commands you will be prompted for your username/admin@EXAMPLE.COM principal password.

- Extract the keytab file:

      kadmin -q "ktadd -k keytab.kdc02 host/kdc02.example.com"

- There should now be a `keytab.kdc02` in the current directory, move the file to `/etc/krb5.keytab`:

      sudo mv keytab.kdc02 /etc/krb5.keytab

  If the path to the `keytab.kdc02` file is different adjust accordingly.

  Also, you can list the principals in a Keytab file, which can be useful when troubleshooting, using the klist utility:

      sudo klist -k /etc/krb5.keytab

- Next, there needs to be a `kpropd.acl` file on each KDC that lists all KDCs for the Realm. For example, on both primary and secondary KDC, create `/etc/krb5kdc/kpropd.acl`:

      host/kdc01.example.com@EXAMPLE.COM
      host/kdc02.example.com@EXAMPLE.COM

- Create an empty database on the Secondary KDC:

      sudo kdb5_util -s create

- Now start the kpropd daemon, which listens for connections from the kprop utility. kprop is used to transfer dump files:

      sudo kpropd -S

- From a terminal on the Primary KDC, create a dump file of the principal database:

      sudo kdb5_util dump /var/lib/krb5kdc/dump

- Extract the Primary KDC's keytab file and copy it to `/etc/krb5.keytab`:

      kadmin -q "ktadd -k keytab.kdc01 host/kdc01.example.com"
      sudo mv keytab.kdc01 /etc/kr5b.keytab

  Make sure there is a host for kdc01.example.com before extracting the Keytab.

- Using the kprop utility push the database to the Secondary KDC:

      sudo kprop -r EXAMPLE.COM -f /var/lib/krb5kdc/dump kdc02.example.com

  There should be a SUCCEEDED message if the propagation worked. If there is an error message check `/var/log/syslog` on the secondary KDC for more information.

  You may also want to create a cron job to periodically update the database on the Secondary KDC. For example, the following will push the database every hour:

      # m h  dom mon dow   command
      0 * * * * /usr/sbin/kdb5_util dump /var/lib/krb5kdc/dump && /usr/sbin/kprop -r EXAMPLE.COM -f /var/lib/krb5kdc/dump kdc02.example.com

- Back on the Secondary KDC, create a stash file to hold the Kerberos master key:

      sudo kdb5_util stash

- Finally, start the krb5-kdc daemon on the Secondary KDC:

      sudo /etc/init.d/krb5-kdc start

The Secondary KDC should now be able to issue tickets for the Realm. You can test this by stopping the krb5-kdc daemon on the Primary KDC, then use kinit to request a ticket. If all goes well you should receive a ticket from the Secondary KDC.

### Kerberos Linux Client

This section covers configuring a Linux system as a Kerberos client. This will allow access to any kerberized services once a user has successfully logged into the system.

#### Installation

In order to authenticate to a Kerberos Realm, the krb5-user and libpam-krb5 packages are needed, along with a few others that are not strictly necessary but make life easier. To install the packages enter the following in a terminal prompt:

    sudo apt-get install krb5-user libpam-krb5 libpam-ccreds auth-client-config

The auth-client-config package allows simple configuration of PAM for authentication from multiple sources, and the libpam-ccreds will cache authentication credentials allowing you to login in case the Key Distribution Center (KDC) is unavailable. This package is also useful for laptops that may authenticate using Kerberos while on the corporate network, but will need to be accessed off the network as well.

#### Configuration

To configure the client in a terminal enter:

    sudo dpkg-reconfigure krb5-config

You will then be prompted to enter the name of the Kerberos Realm. Also, if you don't have DNS configured with Kerberos SRV records, the menu will prompt you for the hostname of the Key Distribution Center (KDC) and Realm Administration server.

The dpkg-reconfigure adds entries to the `/etc/krb5.conf` file for your Realm. You should have entries similar to the following:

    [libdefaults]
            default_realm = EXAMPLE.COM
    ...
    [realms]
            EXAMPLE.COM = }
                    kdc = 192.168.0.1
                    admin_server = 192.168.0.1
            }

You can test the configuration by requesting a ticket using the kinit utility. For example:

    kinit steve@EXAMPLE.COM
    Password for steve@EXAMPLE.COM:

When a ticket has been granted, the details can be viewed using klist:

    klist
    Ticket cache: FILE:/tmp/krb5cc_1000
    Default principal: steve@EXAMPLE.COM

    Valid starting     Expires            Service principal
    07/24/08 05:18:56  07/24/08 15:18:56  krbtgt/EXAMPLE.COM@EXAMPLE.COM
            renew until 07/25/08 05:18:57

    Kerberos 4 ticket cache: /tmp/tkt1000
    klist: You have no tickets cached

Next, use the auth-client-config to configure the libpam-krb5 module to request a ticket during login:

    sudo auth-client-config -a -p kerberos_example

You will should now receive a ticket upon successful login authentication.

### Resources

- For more information on Kerberos see the MIT Kerberos site.

- The Ubuntu Wiki Kerberos page has more details.

- O'Reilly's Kerberos: The Definitive Guide is a great reference when setting up Kerberos.

- Also, feel free to stop by the #ubuntu-server IRC channel on Freenode if you have Kerberos questions.

## Kerberos and LDAP

Replicating a Kerberos principal database between two servers can be complicated, and adds an additional user database to your network. Fortunately, MIT Kerberos can be configured to use an LDAP directory as a principal database. This section covers configuring a primary and secondary kerberos server to use OpenLDAP for the principal database.

### Configuring OpenLDAP

First, the necessary schema needs to be loaded on an OpenLDAP server that has network connectivity to the Primary and Secondary KDCs. The rest of this section assumes that you also have LDAP replication configured between at least two servers. For information on setting up OpenLDAP see .

It is also required to configure OpenLDAP for TLS and SSL connections, so that traffic between the KDC and LDAP server is encrypted. See for details.

- To load the schema into LDAP, on the LDAP server install the krb5-kdc-ldap package. From a terminal enter:

      sudo apt-get install krb5-kdc-ldap

- Next, extract the `kerberos.schema.gz` file:

      sudo gzip -d /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz
      sudo cp /usr/share/doc/krb5-kdc-ldap/kerberos.schema /etc/ldap/schema/

- The kerberos schema needs to be added to the cn=config tree. The procedure to add a new schema to slapd is also detailed in .

- First, create a configuration file named `schema_convert.conf`, or a similar descriptive name, containing the following lines:

      include /etc/ldap/schema/core.schema
      include /etc/ldap/schema/collective.schema
      include /etc/ldap/schema/corba.schema
      include /etc/ldap/schema/cosine.schema
      include /etc/ldap/schema/duaconf.schema
      include /etc/ldap/schema/dyngroup.schema
      include /etc/ldap/schema/inetorgperson.schema
      include /etc/ldap/schema/java.schema
      include /etc/ldap/schema/misc.schema
      include /etc/ldap/schema/nis.schema
      include /etc/ldap/schema/openldap.schema
      include /etc/ldap/schema/ppolicy.schema
      include /etc/ldap/schema/kerberos.schema

- Create a temporary directory to hold the LDIF files:

      mkdir /tmp/ldif_output

- Now use slapcat to convert the schema files:

      slapcat -f schema_convert.conf -F /tmp/ldif_output -n0 -s "cn={12}kerberos,cn=schema,cn=config" > /tmp/cn=kerberos.ldif

  Change the above file and path names to match your own if they are different.

- Edit the generated `/tmp/cn\=kerberos.ldif` file, changing the following attributes:

      dn: cn=kerberos,cn=schema,cn=config
      ...
      cn: kerberos

  And remove the following lines from the end of the file:

      structuralObjectClass: olcSchemaConfig
      entryUUID: 18ccd010-746b-102d-9fbe-3760cca765dc
      creatorsName: cn=config
      createTimestamp: 20090111203515Z
      entryCSN: 20090111203515.326445Z#000000#000#000000
      modifiersName: cn=config
      modifyTimestamp: 20090111203515Z

  The attribute values will vary, just be sure the attributes are removed.

- Load the new schema with ldapadd:

      ldapadd -x -D cn=admin,cn=config -W -f /tmp/cn\=kerberos.ldif

- Add an index for the krb5principalname attribute:

      ldapmodify -x -D cn=admin,cn=config -W
      Enter LDAP Password:
      dn: olcDatabase={1}hdb,cn=config
      add: olcDbIndex
      olcDbIndex: krbPrincipalName eq,pres,sub

      modifying entry "olcDatabase={1}hdb,cn=config"

- Finally, update the Access Control Lists (ACL):

      ldapmodify -x -D cn=admin,cn=config -W
      Enter LDAP Password:
      dn: olcDatabase={1}hdb,cn=config
      replace: olcAccess
      olcAccess: to attrs=userPassword,shadowLastChange,krbPrincipalKey by dn="cn=admin,dc=exampl
       e,dc=com" write by anonymous auth by self write by * none
      -
      add: olcAccess
      olcAccess: to dn.base="" by * read
      -
      add: olcAccess
      olcAccess: to * by dn="cn=admin,dc=example,dc=com" write by * read

      modifying entry "olcDatabase={1}hdb,cn=config"

That's it, your LDAP directory is now ready to serve as a Kerberos principal database.

### Primary KDC Configuration

With OpenLDAP configured it is time to configure the KDC.

- First, install the necessary packages, from a terminal enter:

      sudo apt-get install krb5-kdc krb5-admin-server krb5-kdc-ldap

- Now edit `/etc/krb5.conf` adding the following options to under the appropriate sections:

      [libdefaults]
              default_realm = EXAMPLE.COM

      ...

      [realms]
              EXAMPLE.COM = {
                      kdc = kdc01.example.com
                      kdc = kdc02.example.com
                      admin_server = kdc01.example.com
                      admin_server = kdc02.example.com
                      default_domain = example.com
                      database_module = openldap_ldapconf
              }

      ...

      [domain_realm]
              .example.com = EXAMPLE.COM

      ...

      [dbdefaults]
              ldap_kerberos_container_dn = dc=example,dc=com

      [dbmodules]
              openldap_ldapconf = {
                      db_library = kldap
                      ldap_kdc_dn = "cn=admin,dc=example,dc=com"

                      # this object needs to have read rights on
                      # the realm container, principal container and realm sub-trees
                      ldap_kadmind_dn = "cn=admin,dc=example,dc=com"

                      # this object needs to have read and write rights on
                      # the realm container, principal container and realm sub-trees
                      ldap_service_password_file = /etc/krb5kdc/service.keyfile
                      ldap_servers = ldaps://ldap01.example.com ldaps://ldap02.example.com
                      ldap_conns_per_server = 5
              }

  Change example.com, dc=example,dc=com, cn=admin,dc=example,dc=com, and ldap01.example.com to the appropriate domain, LDAP object, and LDAP server for your network.

- Next, use the kdb5_ldap_util utility to create the realm:

      sudo kdb5_ldap_util -D  cn=admin,dc=example,dc=com create -subtrees dc=example,dc=com -r EXAMPLE.COM -s -H ldap://ldap01.example.com

- Create a stash of the password used to bind to the LDAP server. This password is used by the ldap_kdc_dn and ldap_kadmin_dn options in `/etc/krb5.conf`:

      sudo kdb5_ldap_util -D  cn=admin,dc=example,dc=com stashsrvpw -f /etc/krb5kdc/service.keyfile cn=admin,dc=example,dc=com

- Copy the CA certificate from the LDAP server:

      scp ldap01:/etc/ssl/certs/cacert.pem .
      sudo cp cacert.pem /etc/ssl/certs

  And edit `/etc/ldap/ldap.conf` to use the certificate:

      TLS_CACERT /etc/ssl/certs/cacert.pem

  The certificate will also need to be copied to the Secondary KDC, to allow the connection to the LDAP servers using LDAPS.

You can now add Kerberos principals to the LDAP database, and they will be copied to any other LDAP servers configured for replication. To add a principal using the kadmin.local utility enter:

    sudo kadmin.local
    Authenticating as principal root/admin@EXAMPLE.COM with password.
    kadmin.local:  addprinc -x dn="uid=steve,ou=people,dc=example,dc=com" steve
    WARNING: no policy specified for steve@EXAMPLE.COM; defaulting to no policy
    Enter password for principal "steve@EXAMPLE.COM":
    Re-enter password for principal "steve@EXAMPLE.COM":
    Principal "steve@EXAMPLE.COM" created.

There should now be krbPrincipalName, krbPrincipalKey, krbLastPwdChange, and krbExtraData attributes added to the uid=steve,ou=people,dc=example,dc=com user object. Use the kinit and klist utilities to test that the user is indeed issued a ticket.

If the user object is already created the -x dn="..." option is needed to add the Kerberos attributes. Otherwise a new principal object will be created in the realm subtree.

### Secondary KDC Configuration

Configuring a Secondary KDC using the LDAP backend is similar to configuring one using the normal Kerberos database.

- First, install the necessary packages. In a terminal enter:

      sudo apt-get install krb5-kdc krb5-admin-server krb5-kdc-ldap

- Next, edit `/etc/krb5.conf` to use the LDAP backend:

      [libdefaults]
              default_realm = EXAMPLE.COM

      ...

      [realms]
              EXAMPLE.COM = {
                      kdc = kdc01.example.com
                      kdc = kdc02.example.com
                      admin_server = kdc01.example.com
                      admin_server = kdc02.example.com
                      default_domain = example.com
                      database_module = openldap_ldapconf
              }

      ...

      [domain_realm]
              .example.com = EXAMPLE.COM

      ...

      [dbdefaults]
              ldap_kerberos_container_dn = dc=example,dc=com

      [dbmodules]
              openldap_ldapconf = {
                      db_library = kldap
                      ldap_kdc_dn = "cn=admin,dc=example,dc=com"

                      # this object needs to have read rights on
                      # the realm container, principal container and realm sub-trees
                      ldap_kadmind_dn = "cn=admin,dc=example,dc=com"

                      # this object needs to have read and write rights on
                      # the realm container, principal container and realm sub-trees
                      ldap_service_password_file = /etc/krb5kdc/service.keyfile
                      ldap_servers = ldaps://ldap01.example.com ldaps://ldap02.example.com
                      ldap_conns_per_server = 5
              }

- Create the stash for the LDAP bind password:

      sudo kdb5_ldap_util -D  cn=admin,dc=example,dc=com stashsrvpw -f /etc/krb5kdc/service.keyfile cn=admin,dc=example,dc=com

- Now, on the Primary KDC copy the `/etc/krb5kdc/.k5.EXAMPLE.COM` Master Key stash to the Secondary KDC. Be sure to copy the file over an encrypted connection such as scp, or on physical media.

      sudo scp /etc/krb5kdc/.k5.EXAMPLE.COM steve@kdc02.example.com:~
      sudo mv .k5.EXAMPLE.COM /etc/krb5kdc/

  Again, replace EXAMPLE.COM with your actual realm.

- Finally, start the krb5-kdc daemon:

      sudo /etc/init.d/krb5-kdc start

You now have redundant KDCs on your network, and with redundant LDAP servers you should be able to continue to authenticate users if one LDAP server, one Kerberos server, or one LDAP and one Kerberos server become unavailable.

### Resources

- The Kerberos Admin Guide has some additional details.

- For more information on kdb5_ldap_util see Section 5.6 and the kdb5_ldap_util man page.

- Another useful link is the krb5.conf man page.

- Also, see the Kerberos and LDAP Ubuntu wiki page.