Fwd: SASL LDAP authentication

Martin Schweizer schweizer.martin at gmail.com
Thu Sep 24 15:17:07 EDT 2009


Hello

Sorry for the delay but I was out the country and need some time for
the translation, Below you find my smal tutorial. Good luck!

(Be careful the lines are probably wrapped).

FreeBSD 7.2: Authentication against Windows 2003 Domain controller
over Kerberos5
=================================================================================


The following setup I use to authenticate users on a mail server
(Cyrus Imapd) againts Active Directory (but you can use any
other services too). In this case FreeBSD works as a Kerberos5 client.
Afterwoods I'm able to authenticate with Kerberos5,
PAM and Cyrus SASL (over saslauthd -a PAM or -a Kerberos5).


/etc/krb5.keytab
================

The first step is to create a user in Active Directory (see Windows
domain controller) for the Unix host. krb5.keytab you need normaly
only for services requests (for example from saslauthd -a kerberos5)

acsvfbsd06# ktutil -v list
FILE:/etc/krb5.keytab:

Vno  Type              Principal                                  Date
 4  arcfour-hmac-md5  host/acsvfbsd06.acutronic.ch at ACUTRONIC.CH  2009-09-08

ktutil: krb5_kt_start_seq_get krb4:/etc/srvtab: open(/etc/srvtab): No
such file or directory

Hint: The entries in /etc/srvtab will not be used in this case and can
be ignored. This only for KerberosIV.

To create a /etc/krb5.keytab file you have first to export it from a
domain controller and bind it to the above user name:

C:\Programme\Support Tools>ktpass princ
host/acsvfbsd06.domain.tld at DOMAIN.TLD -crypto RC4-HMAC-NT -ptype
KRB5_NT_SRV_INST -mapuser acsvfbsd06 -pass password out 21.keytab
Targeting domain controller: acsv3k04.domain.tld
Using legacy password setting method
Successfully mapped host/acsvfbsd06.domain.tld to acsvfbsd06.
WARNING: pType and account type do not match. This might cause  problems.
Key created.
Output keytab to 21.keytab:
Keytab version: 0x502
keysize 76 host/acsvfbsd06.domain.tld at DOMAIN.TLD ptype 2 (KRB5_NT_SRV_INST)
vno 4 etype 0x17 (RC4-HMAC) keylength 16 (0x5f92140f96a5ffbfa9fdf8fbae1ed02b)


Important: pytype should be KRB5_NT_SRV_INST! In any other case it
will not work. This is because Kerberos5 looks in this
file and search this type of key. If the type is wrong you get under
different cirscumstance different error messages in

/var/log/auth.log:

- saslauthd -a pam
Sep  2 08:42:22 acsvfbsd06 saslauthd[772]: pam_krb5:
verify_krb_v5_tgt(): krb5_kt_read_service_key(): Key table entry not
found

- saslauthd -a kerberos5
Sep  2 08:42:22 acsvfbsd06 saslauthd[42062]: do_auth         : auth
failure: [user=user][service=imap] [realm=] [mech=kerberos5]
[reason=krb5_verify_user_optfailed]


After you create the keytab file you have to securly transfer the file
to the FreeBSD host. If there exists one you can import the new key in
/etc/krb5.keytab as following:

ktutil copy /usr/home/martin/21.keytab /etc/krb5.keytab

The file /etc/krb5.keytab has (after the creation) the following rights:

-rw-------  1 root  wheel    86B  8 Sep 08:20 krb5.keytab


kinit
=====
- The settings from /etc/krb5.conf will be used.
- kinit creates user owned Kerberos tickes. It's located under
/tmp/krb5cc_<uid>, (for example kinit root => /tmp/krb5cc_0)

You can use kinit to test the basic Kerberos mechanism on FreeBSD
(without parameters). Then /etc/krb5.keytab will not be used.


acsvfbsd06# klist -v
Credentials cache: FILE:/tmp/krb5cc_0
       Principal: martin at DOMAIN.TLD
   Cache version: 4

Server: krbtgt/DOMAIN.TLD at DOMAIN.TLD
Ticket etype: arcfour-hmac-md5, kvno 2
Auth time:  Sep  8 07:40:45 2009
End time:   Sep  8 17:40:25 2009
Renew till: Sep 15 07:40:45 2009
Ticket flags: renewable, initial, pre-authenticated
Addresses: IPv4:192.168.x.y

Server: ldap/acsv3k04.domain.tld at DOMAIN.TLD
Ticket etype: arcfour-hmac-md5, kvno 22
Auth time:  Sep  8 07:40:45 2009
Start time: Sep  8 07:40:50 2009
End time:   Sep  8 17:40:25 2009
Ticket flags: pre-authenticated, ok-as-delegate
Addresses: IPv4:192.168.x.y

kinit -k <username> can be used to test the keytab file. If you get no
message then the authentication is ok and the tickets will deleted
imediatly. If you get init: krb5_get_init_creds: Additional
pre-authentication required, then only the pre-authentication is
failed (see under Windows domain controller).

ldapsearch
==========

Important: kinit should be executed before!

With ldapsearch you can test the ldap functionality against the domain
controller:

acsvfbsd06# ldapsearch -v -LLL -b
"OU=Mitgliedsserver,OU=ACH,DC=domain,DC=tld" -h acsv3k04.domain.tld
description
ldap_initialize( ldap://acsv3k04.domain.tld )
SASL/GSSAPI authentication started
SASL username: martin at DOMAIN.TLD
SASL SSF: 56
SASL data security layer installed.
filter: (objectclass=*)
requesting: description
dn: OU=Mitgliedsserver,OU=ACH,DC=domain,DC=tld
[snip]

Important: If you use default_etypes_des in your etc/krb5.conf,
ldapsearch will fail.

After the first ldapsearch query you get an additional Kerberos ticket
(see under kinit).



/etc/krb5.conf
==============
[libdefaults]
       default_realm = DOMAIN.TLD

[realms]
   DOMAIN.TLD= {
       kdc = acsv3k04.domain.tld:88
       }

[domain_realm]
       domain.tld = DOMAIN.TLD
       .domain.tld = DOMAIN.TLD
       .acsv3k04.domain.tld = DOMAIN.TLD
       acsv3k04.domain.tld = DOMAIN.TLD
       .acsvfbsd06.domain.tld = DOMAIN.TLD
       acsvfbsd06.domain.tld = DOMAIN.TLD
       acsvfbsd06 = DOMAIN.TLD


/etc/resolv.conf
================

domain domain.tld
nameserver 192.168.x.y



/etc/hosts
==========


With the settings below you get no DNS overhead.

192.168.10.2    acsv3k04.domain.tld


Cyrus SASL
==========


First you need to compile Cyrus SASL with all authentication mechanisms:

acsvfbsd06# saslauthd -h
usage: saslauthd [options]

option information:
 -a <authmech>  Selects the authentication mechanism to use.
 -c             Enable credential caching.
 -d             Debugging (don't detach from tty, implies -V)
 -r             Combine the realm with the login before passing to
authentication mechanism
                Ex. login: "foo" realm: "bar" will get passed as
login: "foo at bar"
                The realm name is passed untouched.
 -O <option>    Optional argument to pass to the authentication
                mechanism.
 -l             Disable accept() locking. Increases performance, but
                may not be compatible with some operating systems.
 -m <path>      Alternate path for the saslauthd working directory,
                must be absolute.
 -n <procs>     Number of worker processes to create.
 -s <kilobytes> Size of the credential cache (in kilobytes)
 -t <seconds>   Timeout for items in the credential cache (in seconds)
 -v             Display version information and available mechs
 -V             Enable verbose logging
 -h             Display this message.

saslauthd 2.1.23
authentication mechanisms: sasldb getpwent kerberos5 pam rimap ldap

saslauthd  you start in /etc/rc.conf with -a pam or -a kerberos5


PAM
===

In my setup I use PAM for central authentication. If you use Cyrus
SASL/Imapd you need the service name "imap". So the
correspondend file in /etc/pam.d should have the name imap.

/etc/pam.d/imap:
auth            required       pam_krb5.so  try_first_pass no_user_check
account         required       pam_krb5.so
password        required       pam_krb5.so
session         required       pam_krb5.so


pam_krb5.so:
Hint: pam_krb5.so do not check the fields Vno and encryption
(arcfour-hmac-md5) from the keytab file (see the source code in
/usr/src/lib/libpam/modules/pam_krb5).

pam_krb5.so looks for a principal
host/acsvfbsd06.domain.tld at DOMAIN.TLD with the type KRB5_NT_SRV_INST
(see krb5.keytab/ktpass)

In the actual version of /usr/src/lib/libpam/modules/pam_krb5 there is
a long outstanding bug (see PR
http://www.freebsd.org/cgi/query-pr.cgi?pr=76678&cat=). The problem is
the authentication is only successfully if the authenticated user is
also in the local FreeBSD passwd file. To change this you have to
apply the patch below an set the option no_user_check in
/etc/pam.d/imap (see PAM).

Patch:
--- pam_krb5.c.orig      Tue Feb 10 10:13:20 2004
+++ pam_krb5.c   Sun Jan  9 23:58:36 2005
@@ -89,6 +89,7 @@
 #define PAM_OPT_FORWARDABLE     "forwardable"
 #define PAM_OPT_NO_CCACHE       "no_ccache"
 #define PAM_OPT_REUSE_CCACHE    "reuse_ccache"
+#define PAM_OPT_NO_USER_CHECK   "no_user_check"
 /*
 * authentication management
@@ -213,11 +214,13 @@
                PAM_LOG("PAM_USER Redone");
        }
-        pwd = getpwnam(user);
-        if (pwd == NULL) {
-                retval = PAM_USER_UNKNOWN;
-                goto cleanup2;
-        }
+        if (!openpam_get_option(pamh, PAM_OPT_NO_USER_CHECK)) {
+                pwd = getpwnam(user);
+                if (pwd == NULL) {
+                        retval = PAM_USER_UNKNOWN;
+                        goto cleanup2;
+                }
+        }
        PAM_LOG("Done getpwnam()");





Windows domain controller
=========================

As a directory you can use the following article:
- http://technet.microsoft.com/en-us/library/bb742433.aspx
(Step-by-Step Guide to Kerberos 5 (krb5 1.0) Interoperability )
- Windows Security and Directory Services for UNIX v1.0 (onlsy
available on download.microsoft.com).

As a first step you should create a user which has the same name as
your FreeBSD host. This user name you need in combination with ktpass
(see krb5.keytab). Additional your FreeBSD host should be resolvable
by DNS with PTR and A record.

Do not use the Support tools from Windows 2000, because ktpass has not
the same options (for example encryption).

If you see error messages in the Eventlog (Security) on your domain
controller like:

(sorry only in german available)

Ereignistyp:    Fehlerüberw.
Ereignisquelle: Security
Ereigniskategorie:      Kontoanmeldung
Ereigniskennung:        675
Datum:          08.09.2009
Zeit:           08:22:00
Benutzer:               NT-AUTORITÄT\SYSTEM
Computer:       ACSV3K04
Beschreibung:
Fehlgeschlagene Vorbestätigung:
       Benutzername:   martin
       Benutzerkennung:                ACH\martin
       Dienstname:     krbtgt/DOMAIN.TLD
       Vorauthentifizierungstyp:       0x0
       Fehlercode:     0x19
       Clientadresse:  192.168.20.5

... then the user name is successfully authenticated. The error shows
only the pre-authentication is failed see:

http://support.microsoft.com/kb/230476/en-us:

0x19 (KDC_ERR_PREAUTH_REQUIRED) "Additional pre-authentication"
The client did not send pre-authorization, or did not send the
appropriate type of pre-authorization, to receive a ticket.
The client will retry with the appropriate kind of pre-authorization
(the KDC returns the pre-authentication type in the
error). Many Kerberos implementations will start off without
preauthenticated data and only add it in a subsequent request
when it sees this error. In this case, this error can safely be ignored.



Firewall
========
You need the following ports: 88 (for Kerberos), 53 (for DNS) and 389
(for ldap).


DNS
===
Therewith you have no DNS resolve problems it is a good idea to use a
domain DNS server in /etc/resolv.conf.

You need also this DNS record:
_kerberos           IN  TXT     DOMAINT.TLD


Links
=====

- Kerberos: http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kerberos5.html
- PAM: http://www.freebsd.org/doc/en_US.ISO8859-1/articles/pam/index.html
- Principal/ktpass: http://www.grolmsnet.de/kerbtut/


2009/9/21 Thomas Vogt <tv at solnet.ch>:
> Hi
>
> Martin Schweizer schrieb:
>>
>> Hello Jack
>>
>> I was in the same situation as you in the past two months. My goal was
>> to authenticate between my FreeBSD mail servers  (Cyrus imapd /
>> sendmail) and Active Directory. I find that the best way was to
>> authenticate by KerberosV (by saslauthd -a kerberos5 or -a pam). Now
>> all is workig as expected (after really hard work...). After the work
>> was done I've written a small tutorial (until now only in
>> german...:-))). Do you are interessted?
>
> Can you send me this tutorial too? I can read german :)
>
> Regards,
> Thomas
>
>>
>> Regards,
>>
>>
>>
>> 2009/9/14 Jackie Hunt <jackie at yuma.colostate.edu>:
>>>
>>> Hi all,
>>>
>>> I am trying to get authenticated SMTP running here on campus, and we are
>>> wanting to authenticate against Active Directory.  We are running
>>> sendmail,
>>> and I've been able to get it to work using the UNIX password file.
>>>  However,
>>> I'm having trouble when I try to use ldap to authenticate.
>>>
>>> I'm working on RedHat ES rel4 with cyrus-sasl 2.1.19.   My first question
>>> is
>>> whether or not cyrus-sasl-lib is required for this to work?  It's not
>>> installed on my test box.  However, I tried another Linux system we have
>>> that does have cyrus-sasl-lib installed, and things still don't work.  I
>>> know I'm missing something crucial, so any help would be greatly
>>> appreciated.
>>>
>>> When I run saslauthd -v I see:
>>>
>>> saslauthd 2.1.19
>>> authentication mechanisms: getpwent kerberos5 pam rimap shadow ldap
>>>
>>> So, I'm assuming it has everything it needs compiled in to do ldap
>>> authentication.
>>>
>>> I then edited the /etc/sysconfig/saslauthd file, and changed the MECH=pam
>>> line to MECH=ldap.
>>>
>>> Then I created a /etc/saslauthd.conf file with the contents:
>>>
>>> ldap_servers: ldap://129.82.xxx.xxx/
>>> ldap_bind_dn: cn=xxxxx,ou=xxxxxxxxxxx,dc=ColoState,dc=edu
>>> ldap_password: xxxxxxxx
>>> ldap_filter: (sAMAccountName=%u)
>>> ldap_search_base: dc=colostate,dc=edu
>>> ldap_auth_method: bind
>>>
>>> Then I start saslauthd the following command:
>>>
>>> /usr/sbin/saslauthd -a ldap -d -O /etc/saslauthd.conf
>>>
>>> Then I run a command to test it:
>>>
>>> /usr/sbin/testsaslauthd -u jackie -p xxxxx
>>>
>>> And the output I see is:
>>>
>>> saslauthd[8045] :main            : num_procs  : 5
>>> saslauthd[8045] :main            : mech_option: /etc/saslauthd.conf
>>> saslauthd[8045] :main            : run_path   : /var/run/saslauthd
>>> saslauthd[8045] :main            : auth_mech  : ldap
>>> saslauthd[8045] :ipc_init        : using accept lock file:
>>> /var/run/saslauthd/mux.accept
>>> saslauthd[8045] :detach_tty      : master pid is: 0
>>> saslauthd[8045] :ipc_init        : listening on socket:
>>> /var/run/saslauthd/mux
>>> saslauthd[8045] :main            : using process model
>>> saslauthd[8046] :get_accept_lock : acquired accept lock
>>> saslauthd[8045] :have_baby       : forked child: 8046
>>> saslauthd[8045] :have_baby       : forked child: 8047
>>> saslauthd[8045] :have_baby       : forked child: 8048
>>> saslauthd[8045] :have_baby       : forked child: 8049
>>> saslauthd[8046] :rel_accept_lock : released accept lock
>>> saslauthd[8047] :get_accept_lock : acquired accept lock
>>> saslauthd[8046] :do_auth         : auth failure: [user=jackie]
>>> [service=imap] [realm=] [mech=ldap] [reason=Unknown]
>>> saslauthd[8046] :do_request      : response: NO
>>> saslauthd[8047] :rel_accept_lock : released accept lock
>>>
>>> I don't see where it is trying to authenticate as the ldap_bind I
>>> specified
>>> in the configuration file.  Should it do that first?
>>>
>>> I would really appreciate any help.  I've been struggling with this for
>>> several days.
>>>
>>> Thanks so much!
>>>
>>> Jackie Hunt
>>> Colorado State University
>>>
>>
>>
>>
>
>



--
Martin Schweizer
schweizer.martin at gmail.com
Tel.: +41 32 512 48 54 (VoIP)
Fax: +1 619 3300587


More information about the Cyrus-sasl mailing list