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 - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html