users file: =~ and User-Password

Phil Mayers p.mayers at imperial.ac.uk
Fri Mar 24 12:02:00 CET 2006


Stefan Winter wrote:
> Hi,
> 
> I'm trying to understand what exactly happens in the users file when 
> processing User-Password. The situation I'm seeing here is in a rather 
> complex scenario, and the results are not quite what I would expect. In 
> short, when a MS-CHAP'ed request comes in and users contains a check
> User-Password =~ (foo|bar), then even though there is no User-Password 
> attribute in the request itself, it matches.
> The long story, for those still reading, is:
> * mySQL database with our "nice" users. Nice means, they have a single 
> password for all of our services (ASMTP, IMAP, VPN, Dial-Up, Groupware).
> * some users have for ancient reasons two different passwords, one for 
> VPN&Dial-Up, one for the rest.
> * these users are handled in the users file, with
>   uname User-Password =~ (foo|bar), Auth-Type := Accept

That will not work. How is the mschap module supposed to know which 
plaintext password to perform the challenge/response with? In fact, 
since the "value" is a regexp, how is it supposed to even know what the 
alternative values are (you cannot in general reverse a regexp to get 
the matching inputs).


> * The processing order in authorize and authenticate is:
> 
> authorize {
>         preprocess
>         nas_auth_log
>         suffix
>         mschap
>         files
>         eap
>         sql
> }
> 
> authenticate {
>         Auth-Type MS-CHAP {
>                 mschap
>         }
>         eap
> }
> 
> Now, -X shows that first authorize->mschap comes into action and sets the 
> Auth-Type to MS-CHAP (fine). It does *NOT* set a User-Password attribute 
> because this can only be retrieved later during authorize->sql. 
> The next module to come is authorize->files. There, in my opinion, the 
> above-mentioned line that contains User-Password =~ (foo|bar) SHOULD NOT 
> match, because there is no User-Password attribute in the request.
> But: users DOES match (when one of the passwords matches the CHAP challenge) 

Hmm. You're probably right - it should never match.

Given that it should never match, why don't you just delete those 
entries? What are you expecting them to do? Are you expecting that to 
somehow try two passwords in turn for a user, because it won't. See 
below for a possible solution.

> and sets Auth-Type to Accept. This can only mean that files does some 
> auto-validating against the CHAP challenge, where it should only make a 
> simple string comparison (not even that, since the attribute isn't even 
> there, it should just do nothing).

No. The "files" modules definitely does nothing like that.

> Now you could say, so what, the user gets accepted after all, so why do you 
> care? The reason is that as soon as Auth-Type is set to Accept, 
> authenticate->mschap isn't called any more, and so the encryption seeds and 
> and attributes are not set. That way, people end up being accepted by RADIUS, 
> but the VPN concentrator denies access anyways.
> I'm aware I can get around this by using Auth-Type = Accept, to not override 
> the previously-set MS-CHAP.
> But the real cause is in that a "users" line matches that, according to the 
> documentation of the =~ operator, shouldn't. If you explain me now that the 
> magic MS-CHAP validation is intentional, no problem: I would even submit a 

It's not, and it's not happening. Something else is going on. I would 
have to look at the source to determine what, and am busy a.t.m.

> documentation patch explaining things. But just leaving the hand-waiving 
> undocumented is not good IMHO.

Well, what you're doing (at least, the way you're doing it) is not 
possible. MSCHAP is a challenge/response algorithm, and needs a single 
unambiguous plaintext at the server to validate the response.

You might be able to use the module failover to do something:

modules {
   files files1 {
     (...)
   }
   files files2 {
     (...)
   }
   mschap {
     (...)
   }
}

authorize {
   preprocess
   group {
     sql {
       ok = return
       updated = return
     }
     files1
     mschap {
       fail = 1
       ok = return
     }
     files2
     mschap {
       fail = 1
       ok = return
     }
   }
}

users1:

user User-Password := VPNPASS

users2:

user User-Password := OTHERPASS

...see doc/configureable_failover. It WILL be complicated, and may not 
even work since it's possible the first mschap module failure will leave 
dangling attributes in the reply even when the 2nd one succeeds. You 
could possibly solve that with attr_rewrite, but as you can see it 
starts to get hard.

My advice to you would be to solve the non-technical problem 
non-technically and educate your users to use the correct (VPN) password 
when accessing VPN.



More information about the Freeradius-Users mailing list