On Thu, Mar 06, 2008 at 03:36:27AM +0100, Josip Rodin wrote:
> On Sat, Jul 21, 2007 at 06:08:23PM +0200, joy wrote:
> > Is the mod_auth_radius-2.0.c supposed to work properly with Apache 2.2.x?
> > 
> > I can compile it just fine, but can't get it to work on runtime.
> > 
> > Maybe, like LDAP, this module should become a an AuthBasicProvider?
> 
> I took a hint from mod_auth_xradius' changes for Apache 2.1+, and made the
> patch which is attached... but it still doesn't work. Apache is so annoying
> to debug, I need to compile the server with debugging symbols and run it
> through gdb... :(

Okay, I debugged it a bit further (no help from gdb), and managed to produce
a working patch. The problem that threw me off was the early DECLINED
handling in the authenticate_basic_user() function, which got activated
both when the module was inactive and when the RADIUS server definition
was missing. However, these two conditions are functionally quite different,
so I split the handling in two, with the latter case leaving a warning
in the log file.

The working patch is attached. It allows people to define:
        AuthBasicProvider radius
and everything appears to be working well after that.

-- 
     2. That which causes joy or happiness.
--- libapache-mod-auth-radius-1.5.7.orig/mod_auth_radius-2.0.c
+++ libapache-mod-auth-radius-1.5.7/mod_auth_radius-2.0.c
@@ -300,6 +300,9 @@
 #include "apr_general.h"
 #include "apr_tables.h"
 #include "apr_strings.h"
+/* Apache 2.1+ */
+#include "ap_provider.h"
+#include "mod_auth.h"
 
 module AP_MODULE_DECLARE_DATA radius_auth_module;
 
@@ -1122,8 +1125,11 @@
  * basic authentication...
  */
 
-static int
-authenticate_basic_user(request_rec *r)
+/* common stuff for both Apache 2.0 and 2.1+ */
+int
+authenticate_basic_user_common(request_rec *r,
+                               const char* user,
+                               const char* sent_pw)
 {
   radius_dir_config_rec *rec =
     (radius_dir_config_rec *)ap_get_module_config (r->per_dir_config, &radius_auth_module);
@@ -1131,21 +1137,25 @@
   radius_server_config_rec *scr = (radius_server_config_rec *)
     ap_get_module_config (s->module_config, &radius_auth_module);
   conn_rec *c = r->connection;
-  const char *sent_pw;
   char errstr[MAX_STRING_LEN];
-  int res, min;
+  int min;
   char *cookie;
   char *state = NULL;
   char message[256];
   time_t expires;
   struct stat buf;
   
-  if (!rec->active || !scr->radius_ip)	/*  not active here, or no radius */
-    return DECLINED;                    /*  server declared, decline      */
+  /* not active here, just decline */
+  if (!rec->active)
+    return DECLINED;
+
+  /* no server declared, decline but note for debugging purposes -joy */
+  if (!scr->radius_ip) {
+    ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_WARNING, 0, r->server,
+                 "AuthRadiusActive set, but no RADIUS server IP - missing AddRadiusAuth in this context?");
+    return DECLINED;
+  }
   
-  if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
-    return res;
-
   if (r->user[0] == 0)		/* NUL users can never be let in */
     return HTTP_UNAUTHORIZED;
 
@@ -1227,9 +1237,57 @@
   return OK;
 }
 
+/* Apache 2.1+ */
+static authn_status
+authenticate_basic_user_newargs(request_rec *r,
+                                const char *user,
+                                const char *password)
+{
+  int normalreturnvalue = authenticate_basic_user_common(r, user, password);
+
+  if (normalreturnvalue == OK)
+    return AUTH_GRANTED;
+  else if (normalreturnvalue == HTTP_UNAUTHORIZED)
+    return AUTH_DENIED;
+  else
+    return AUTH_GENERAL_ERROR;
+  /* AUTH_USER_NOT_FOUND would be nice, but the typical RADIUS server
+     never gives any such information, it just sends an Access-Reject
+     packet, no reasons given
+   */
+}
+
+/* Apache 2.0 */
+static int
+authenticate_basic_user(request_rec *r)
+{
+  int res;
+  const char *sent_pw;
+  
+  /* this used to say just if ((res=...)), which relied on the fact that
+     OK is defined as 0, and the other states are non-0, which is then
+     used in a typical C fashion... but it's a bad idea, really, we should
+     explicitly check if it's not OK, whatever that may be -joy
+   */
+  res = ap_get_basic_auth_pw(r, &sent_pw);
+  if (res != OK)
+    return res;
+
+  return authenticate_basic_user_common(r, r->user, sent_pw);
+}
+
+/* Apache 2.1+ */
+static const authn_provider authn_radius_provider = {
+    &authenticate_basic_user_newargs,
+    NULL
+};
+
 static void register_hooks(apr_pool_t *p)
 {
-    ap_hook_check_user_id(authenticate_basic_user,NULL,NULL,APR_HOOK_MIDDLE);
+/* Apache 2.1+ */
+    static const char * const aszPost[]={ "mod_authz_user.c", NULL };
+    ap_register_provider(p, AUTHN_PROVIDER_GROUP, "radius", "0", &authn_radius_provider);
+    ap_hook_check_user_id(authenticate_basic_user,NULL,aszPost,APR_HOOK_MIDDLE);
 }
 
 module AP_MODULE_DECLARE_DATA radius_auth_module =

Reply via email to