Kerberos authentication with Apache in a multi-domain Active Directory

joncs_1

The context

Sometimes people are crazy ! They install Microsoft architectures everywhere : Windows on workstations, a lot of domain controllers and Active Directory. And then MS is regularly see them with their bill and they lose an arm. Since they are still eager to eat chocolate, they decide (which is not bad) to open their information to other technologies. That way the next time a Bill ‘s soldier will see them, they can threaten him (a little) to stop using its products and thus lower the bill.

The next application will be completely done with free software components, and as more Web format than done. The user must connect to the application via a browser using the Windows Integrated authentication.

We arrive and we are happy because it proposes to use the following software :

  • Linux CentOS 5.6
  • Samba 3.5.4
  • Apache 2.2.3
  • Mod_auth_kerb : 5.1
  • Kerberos 1.6.1
  • Php 5.1

And all this in the following environment :

  • OS Workstation : Windows XP et 7
  • Web browser : IE9 et Firefox 4
  • KDC : Windows 2003/2008 R2

A small diagram to illustrate the Active Directory architecture used in this post :

Schéma architecture Active Directory

Schéma architecture Active Directory

 

And a small second :

Schéma architecture 2

Schéma architecture 2

 

Naming rules used in this tutorial

  • Server Linux Apache : serverA
  • Server KDC 2003 dom1.maboite.fr : serverKDC1
  • Server KDC 2008 dom1.maboite.fr : serverKDC2
  • Server KDC 2003 dom2.maboite.fr : serverKDC3

 

Installation

Once the CentOS prepared in a basic version, install the necessary packages :

# yum update
# yum install krb5-workstation
# yum install samba3x samba3x-client
# yum install httpd
# yum install mod_auth_kerb
# yum install ntp
# yum install php php-ldap

Configuration

Date and time

Our server should not be too delayed (<10 min) with the DC domain DOM1.

Customize the file /etc/ntp.conf to synchronize with a time server, then type the following commands :

# service ntpd stop
# ntpdate @TIME_SERVER
# service ntpd start

HOSTS file

The file /etc/hosts must be properly informed in order to join an Active Directory domain :

127.0.0.1           serverA.maboite.fr           serverA

KERBEROS

Customize the file /etc/krb5.conf and adapt the following :

[libdefaults]
  default_realm = DOM1.MABOITE.FR
  default_keytab_name = FILE:/etc/krb5.keytab
  kdc_timesync = 1
  ccache_type = 4
  forwardable = true
  proxiable = true
  fcc-mit-ticketflags = true

[realms]
  DOM1.MABOITE.FR = {
    kdc = @IP serverKDC1
    kdc = @IP serverKDC2
    admin_server = @IP serverKDC1
    admin_server = @IP serverKDC2
 }

[domain_realm]
  MONWORKGROUP = DOM1.MABOITE.FR
  .dom1.maboite.fr = DOM1.MABOITE.FR

[appdefaults]
  kinit = {
  renewable = true
  fowardable = true
  }

Then create file /etc/krb5.keytab :

# touch /etc/krb5.keytab
# chmod 640 /etc/krb5.keytab
# chgrp apache /etc/krb5.keytab

SAMBA

Here is a sample of the configuration file /etc/samba/smb.conf with the necessary parameters:

[global]
 dedicated keytab file = /etc/krb5.keytab
 kerberos method = secrets and keytab
 security = ADS
 server string = SERVERA
 realm = DOM1.MABOITE.FR
 workgroup = MONWORKGROUP
 password server = *

 winbind offline logon = true
 winbind refresh tickets = true
 winbind cache time = 3600
 winbind use default domain = no
 preferred master = no
 domain master = No

Then we will join the Linux server to the Domain 1 :

# /etc/init.d/smb stop
# /etc/init.d/nmb stop
# /etc/init.d/winbind stop
# net cache flush
# kinit admin_account_dom1
# net ads join -U admin_account_dom1
Enter admin_account_dom1's password:

The answer of the last command indicating that the operation went well must be :

Using short domain name -- MONWORKGROUP
Joined 'SERVERA' to realm 'dom1.maboite.fr'

To check :

# net ads testjoin
Join is OK

Then restart SAMBA :

# /etc/init.d/smb start
# /etc/init.d/nmb start
# /etc/init.d/winbind start

KEYTAB

The Web server has successfully joined the AD domain, we now learn the file /etc/krb5.keytab for it to be used by Apache.

# net ads keytab add HTTP -U admin_account_dom1
Processing principals to add...
Enter admin_account_dom1's password:

Verify if the file /etc/krb5.keytab is right :

# ktutil
ktutil:  rkt /etc/krb5.keytab
ktutil:  l
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
1   28 HTTP/serverA.maboite.fr@DOM1.MABOITE.FR
2   28 HTTP/serverA.maboite.fr@DOM1.MABOITE.FR
3   28 HTTP/serverA.maboite.fr@DOM1.MABOITE.FR
4   28         HTTP/serverA@DOM1.MABOITE.FR
5   28         HTTP/serverA@DOM1.MABOITE.FR
6   28         HTTP/serverA@DOM1.MABOITE.FR

APACHE

Customize the file /etc/httpd/conf.d/auth_kerb.conf :

#
# Sample configuration: Kerberos authentication must only be
# used over SSL to prevent replay attacks.  The keytab file
# configured must be readable only by the "apache" user, and
# must contain service keys for "HTTP/www.example.com", where
# "www.example.com" is the FQDN of this server.
#

<Location /logon>
  AuthType Kerberos
  AuthName "Kerberos Login"
  KrbMethodNegotiate On
  KrbMethodK5Passwd On
  KrbAuthRealms DOM1.MABOITE.FR DOM2.MABOITE.FR
  Krb5KeyTab /etc/krb5.keytab
  KrbSaveCredentials On
  KrbServiceName HTTP
  require valid-user
</Location>

The restart Apache :

# /etc/init.d/httpd restart

PHP and LDAP

The following PHP file is given as an example. We will post the PHP variables to verify that the authentication is successful, then we will try to get some information about the user contained in the AD (name, surname, email, …).

Create the php file /var/www/html/logon/index.php and write the following code:

SUPER it works !!<br>

<?php
    foreach($_SERVER as $key_name => $key_value){
      print $key_name . " = " . $key_value . "<br>";
    }
    echo "<br />";

// Info AD DOM1
    $ldaphostDOM1 = "serverKDC1";  // DOM1 server AD
    $ldapportDOM1 = 389;            // port
// Info AD DOM2
    $ldaphostDOM1 = "serverKDC3";  // DOM2 server AD
    $ldapportDOM1 = 389;            // port
// [...] same for other doamins

// User DN DOM1
    $ldaprdnDOM1  = 'CN=LDAP, OU=Comptes techniques, OU=Dom1, DC=dom1, DC=maboite, DC=fr';
    $ldappassDOM1 = 'password';           // User Password
// User DN DOM2
    $ldaprdnDOM2  = 'CN=LDAP, OU=Comptes techniques, OU=Dom2, DC=dom2, DC=maboite, DC=fr';
    $ldappassDOM2 = 'password';           // User password
// [...] same for other domains

// USER DN DOM1
   $dnDOM1 = "OU=Comptes Utilisateurs,OU=dom1, DC=Dom1, DC=maboite, DC=fr"
// DN utilisateurs DOM2
   $dnDOM2 = "OU=Comptes Utilisateurs,OU=dom2, DC=Dom2, DC=maboite, DC=fr"
// [...] same for other domains

// $person is the username et $domain is REALM
   $tab = explode('@',$_SERVER['REMOTE_USER']);
   $person = $tab[0];
   $domain = $tab[1];

   switch ($domain){
         case "DOM1.MABOITE.FR":
           $ldaphost = $ldaphostDOM1;
           $ldapport = $ldapportDOM1;
           $ldaprdn = $ldaprdnDOM1;
           $ldappass = $ldappassDOM1;
           $dn = $dnDOM1;
           break;

         case "DOM2.MABOITE.FR":
           $ldaphost = $ldaphostDOM2;
           $ldapport = $ldapportDOM2;
           $ldaprdn = $ldaprdnDOM2;
           $ldappass = $ldappassDOM2;
           $dn = $dnDOM2,
           break;

         // case [...] same for other domains
         default:
             die( "Unknow user domain : $domain" );
     }

// Connecting to LDAP
    $ldapconn = ldap_connect( $ldaphost, $ldapport )
     or die( "Unable to connect to the LDAP server {$ldaphost}" );

    if ($ldapconn) {
//Connect to LDAP server
     $ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
// Identification
     if ($ldapbind) {
       echo "LDAP connection successfull<br>";
       $filter = "(sAMAccountName=$person)";
       $justthese = array( "cn", "ou", "sn", "givenname", "mail", "memberOf");
       $sr=ldap_search($ldapconn, $dn, $filter, $justthese);
       $info = ldap_get_entries($ldapconn, $sr);
       echo $info["count"]." register.\n";

       for ($i=0; $i<$info["count"]; $i++) {
         echo 'dn is : ' . $info[$i]["dn"] . '<br />';
         echo 'first register cn : ' . $info[$i]["cn"][0] . '<br />';
         echo 'name : ' . $info[$i]["givenname"][0] . '<br />';
         echo 'surname : ' . $info[$i]["sn"][0] . '<br />';
         echo 'first email : ' . $info[$i]["mail"][0] . '<br />';
         $taillememberof = sizeof($info[$i]["memberof"]) -1;
         for ($j=0; $j<$taillememberof; $j++){
           echo 'memberOf ['.$j.'] : ' . $info[$i]["memberof"][$j] . '<br />';
         }
       }
     }else{
       echo "LDAP connction failed";
     }
    }
?>

INTERNET EXPLORER

If the browser is IE, check the configuration options in the Internet :

configuration IE

FIREFOX

In the address bar type about: config then filter with the word « auth.trusted » :

configuration Firefox

RESULTAT

SUPER it works !!

HTTP_ACCEPT = image/jpeg, application/x-ms-application, image/gif, application/xaml+xml,
image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash; [..] */*
HTTP_ACCEPT_LANGUAGE = fr-FR
HTTP_USER_AGENT = Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2;
.NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0;
Tablet PC 2.0; .NET CLR 1.1.4322; .NET4.0C; InfoPath.3)
HTTP_ACCEPT_ENCODING = gzip, deflate
HTTP_HOST = serveurA
HTTP_CONNECTION = Keep-Alive
PATH = /sbin:/usr/sbin:/bin:/usr/bin
SERVER_SIGNATURE =
Apache/2.2.3 (CentOS) Server at serveurA.maboite.fr Port 80

SERVER_SOFTWARE = Apache/2.2.3 (CentOS)
SERVER_NAME = serverA.maboite.fr
SERVER_ADDR = 10.80.133.196
SERVER_PORT = 80
REMOTE_ADDR = 10.80.128.36
DOCUMENT_ROOT = /var/www/html
SERVER_ADMIN = root@localhost
SCRIPT_FILENAME = /var/www/html/logon/index.php
REMOTE_PORT = 52398
REMOTE_USER = MUSER@DOM2.MABOITE.FR
AUTH_TYPE = Negotiate
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.1
REQUEST_METHOD = GET
QUERY_STRING =
REQUEST_URI = /logon/index.php
SCRIPT_NAME = /logon/index.php
PHP_SELF = /logon/index.php
REQUEST_TIME = 1308664098

LDAP connection successfull

1 register.
dn is : CN=USER\, MON,OU=Comptes Collaborateurs,OU=Dom2,DC=dom2,DC=maboite,DC=fr
first register cn : USER, Mon
name : Mon
surname : USER
first email : MUSER@maboite.fr
memberOf [0] : CN=LinuxEXPLOIT,OU=Groupes d'equipes,OU=Dom2,DC=dom2,DC=maboite,DC=fr
memberOf [1] : CN=Utilisateurs Internet,OU=Groupes Applicatifs,OU=Dom2,DC=dom2,DC=maboite,DC=fr
memberOf [2] : CN=Equipe Systeme,OU=Groupes d'equipes,OU=Dom2,DC=dom2,DC=maboite,DC=fr

 

Conclusion

And now it’s over for today. As we have seen, it is possible to allow Windows users to authenticate seamlessly with a website that runs on Linux.

If you have any comments please!

 

Links

4 Responses to Kerberos authentication with Apache in a multi-domain Active Directory

  1. Dave Funk dit :

    By default the system keytab, /etc/krb5.keytab, should only be readable by root.
    For security purposes it would be better to create a separate keytab for the webserver process (EG: /etc/apache2/krb5.keytab ), put the HTTP credentials in that file, and make it readable by apache. That way, if your website gets compromised (EG: bad user PHP code, SQL injection, etc) the only thing the attacker can get is the webserver credentials, the creds for other processes (EG: sshd or smbd) are still safe.

  2. Willa dit :

    Thanks , I’ve recently been searching for info about this topic for a long time and yours is the best I have discovered till now. But, what about the conclusion? Are you sure about the supply?

  3. AirStream dit :

    Sorry.
    Your method is suitable for this?*
    Can you do screenshot to show how it works?

  4. AirStream dit :

    Hey!
    If I need to do authentication with Apache + Samba + Kerberos against Active Directory on website which has for example MediaWiki or another CMS engine. You method is suitable for this.

    User goes to website (MediaWiki page) and has Active Directory username.
    It is possible?

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

*


6 + deux =

You may use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Le site www.tuxlanding.net est sous Licence Creative Common - CC - Paternité - Certains droits réservés
logo : www.gaia10.us