FYI : My workaround for freeradius not sending back an Access-Reject on a failed external script
Patric
patrict at bluebottle.com
Fri May 25 16:20:39 CEST 2007
Hey guys,
Thought it might interest some of you as to how I worked around the
problem where freeradius does not return an Access-Reject if my php
script does not exit successfully (in my case because a user should be
rejected).
The original code that checks the exit status of the script is this :
src/modules/rlm_exec/rlm_exec.c :
/*
* Dispatch an exec method
*/
static int exec_dispatch(void *instance, REQUEST *request)
{
...
if (result != 0) {
radlog(L_ERR, "rlm_exec (%s): External script failed",
inst->xlat_name);
return RLM_MODULE_FAIL;
}
...
return RLM_MODULE_OK;
}
So basically if my script does not return 0, it failed, regardless of
its exit status.
According to the RLM_MODULE_* definitions :
enum {
RLM_MODULE_REJECT, /* 0 - immediately reject the request */
RLM_MODULE_FAIL, /* 1 - module failed, don't reply */
RLM_MODULE_OK, /* 2 - the module is OK, continue */
RLM_MODULE_HANDLED, /* 3 - the module handled the request,
so stop. */
RLM_MODULE_INVALID, /* 4 - the module considers the request
invalid. */
RLM_MODULE_USERLOCK, /* 5 - reject the request (user is
locked out) */
RLM_MODULE_NOTFOUND, /* 6 - user not found */
RLM_MODULE_NOOP, /* 7 - module succeeded without doing
anything */
RLM_MODULE_UPDATED, /* 8 - OK (pairs modified) */
RLM_MODULE_NUMCODES /* 9 - How many return codes there are */
};
So if I wanted to authenticate a user I should *actually* be returning 2.
If I wanted to *reject* the user I should be returning 0.
But according to the code above if I return 2 the external script
failed, and if I return 0, the external script was successful and my
user is authenticated successfully.
This is how I changed the logic :
I *removed* :
...
if (result != 0) {
radlog(L_ERR, "rlm_exec (%s): External script failed",
inst->xlat_name);
return RLM_MODULE_FAIL;
}
...
And replaced it with :
...
switch (result) {
case 0: // Rejected
return RLM_MODULE_REJECT;
break;
case 1: // Failed
return RLM_MODULE_FAIL;
break;
case 2: // OK
break;
case 3: // Handled
return RLM_MODULE_HANDLED;
break;
case 4: // Invalid
return RLM_MODULE_INVALID;
break;
case 5: // UserLock
return RLM_MODULE_USERLOCK;
break;
case 6: // Not Found
return RLM_MODULE_NOTFOUND;
break;
case 7: // No Op
return RLM_MODULE_NOOP;
break;
case 8: // Updated
return RLM_MODULE_UPDATED;
break;
case 9: // Num Codes
return RLM_MODULE_NUMCODES;
break;
default: // Fail
return RLM_MODULE_FAIL;
break;
}
...
In this way, if the result is 2 (user is OK), the process will drop out
of the switch statement, and process the original code for handling a
successful authentication.
Now in my external script I can do :
exit(2); --> User was accepted.
OR
exit(0); --> User was rejected.
I realise that this is a bit of a contradiction for the external script,
because for a reject it is exiting successfully, and for a successful
authentication it is in fact failing with exit code 2. BUT in this way I
can use the codes determined by freeradius in my external script.
I do not think that this is the actual bug that Alan refered to, but it
was a problem in my case.
The original code is actually correct in that the external script *did*
fail, but it was ignoring the exit code to determine what action to take.
I believe that the actual bug is that freeradius does not return a reply
to the authentication request if the status is set to RLM_MODULE_FAIL.
From what I could tell the only time that freeradius replies to a
request is if the status is RLM_MODULE_OK, or RLM_MODULE_REJECT and
possibly RLM_MODULE_USERLOCK.
I hope that this is understandable, I have the whole scenario in my head
but its a bit difficult to verbalise...
Please advise if any of my presumptions or understandings are incorrect,
as I am happy to learn!
Thanks for all your responses to my questions, Im back on track now!
Patrick
----------------------------------------------------------------------
Get a free email address with REAL anti-spam protection.
http://www.bluebottle.com
More information about the Freeradius-Users
mailing list