Multi-domain AD and Users Who Aren't So Bright

McNutt, Justin M. McNuttJ at missouri.edu
Wed Feb 1 22:57:02 CET 2012


So I'm working on a way to Improve the User Experience.  I've gotten a LONG way, but now I'm stuck.  Here's the short/long version (all details, without undue explanation or discussion of what I tried that doesn't work):

WARNING:  This may well be a case of doing it the hard way.  If that's the case, feel free to tell me, but it's not for lack of trying to research this via Google, searching archives of this list, etc.  Just tell me what I'm doing wrong.  I can handle it.  ;)

Okay, here goes:

1)  I created two custom attributes named "My-NT-Domain" and "My-User-Name" and added them to the dictionary file as 3003 and 3004, respectively.

2)  I added sections to sites-enabled/my-virt-server in the "authorize {" like this:

        # Allow host-based authentication for computers in the domain.
        if ( User-Name =~ /host\/[^\.]+\.(.+)/ ) {
                update request {
                        My-User-Name = "%{mschap:User-Name}"
                        My-NT-Domain = "%{1}"
                }
        }
        # Fix the forward slash.
        elsif ( User-Name =~ /([^\/]+)\/(.+)/ ) {
                update request {
                        My-User-Name = "%{2}"
                        My-NT-Domain = "%{1}"
                }
        }
        # New student e-mail format.
        elsif ( User-Name =~ /([^@]+)@mail.missouri.edu/ ) {
                update request {
                        My-User-Name = "%{1}"
                        My-NT-Domain = "TIGERS"
                }
        }

... and so on.

3)  I changed /etc/raddb/modules/mschap to call ntlm_auth like this:

ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --username=%{%{My-User-Name}:-%{mschap:User-Name}} --domain=%{%{My-NT-Domain}:-%{mschap:NT-Domain}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"


So at this point, if a user plugs in the correct "domain\username" stuff, none of the "cleanup" cases match, so my custom attributes are empty, and the usual %{mschap:xx} variables work fine.  If fixes were necessary, the custom attributes take over.

All that works fine.

NOW we want to be able to have a user authenticate without specifying a domain.  In theory, that's no big deal.  If the users NEVER specify a domain at all, I can populate my custom attributes with this:

        if ( ! My-NT-Domain ) {
                    update request {
                            My-User-Name = "%{User-Name}"
                            My-NT-Domain = `/etc/raddb/bin/GetDomain.pl %{User-Name}`
                    }
        }

The "GetDomain.pl" script does a command-line LDAP search (using "ldapsearch") against our AD for %{User-Name}, grabs the dn attribute, matches the AD domain, and returns the NT domain that corresponds.  This also works.

NOW, the problem is that if the user DOES specify "domain\username" correctly, then none of the "cleanup" cases match, so My-NT-Domain is empty.  But since my custom attribute is empty, the Perl script is being called unnecessarily to run the LDAP search.

Solution:

I was still thinking about this as I wrote it, and I modified the "final check" clause (that looks for the total absence of domain hints) and I thought of a way to implicitly resolve the case where the user passes scary characters in the user ID (injection attack) AND the case where the user specified a valid domain\username set of creds at the same time:

# Check special fix-it cases above.
# These could probably be done as a single if statement.
# It was simpler to keep them separate while testing.
  if ( ! My-NT-Domain ) {
                if ( User-Name =~ /^[a-zA-Z0-9]+$/ ) {
                        update request {
                                My-User-Name = "%{User-Name}"
                                My-NT-Domain = `/etc/raddb/bin/GetDomain.pl %{User-Name}`
                        }
          }
  }


This appears to be working.

Overall, I give this solution about a B+.

PROS:
Works in a single forest, multi-domain environment, regardless of any conformity to typical AD domain naming standards.
Makes authentication SIMPLE for the users.
The way I wrote the GetDomain script, it always returns DOMAIN or (null) after only a single LDAP query (efficient).
Combined with judicious use of "radiusd -XC" provides a simple way to correct common typos.
Permits computer-based authentication to work again in multi-domain or non-typical-naming cases (where mschap currently fails).
Still reports the original creds as given by user (in case you still want to report on the cases that needed fixing and resolve the problem at the source, rather than making FR do all the work.
Limited to this virtual server.

CONS:
In many cases - like translating "col.missouri.edu" to "UMC-USERS", the "fixes" are hard-coded.  By comparison, changing the / to a \ works for any domain in a single check.
Doubles (at least) the number of calls to AD in cases where everyone is lazy and leaves out the domain.  I.e. an LDAP call to get the domain plus the authentication itself.
Encourages user ignorance.  (Judgement call.)
Limited to this virtual server.


Thoughts?  Opinions?  Better ways to accomplish any/all of this?

--J




More information about the Freeradius-Users mailing list