I find the function rad_send_request() in /usr/src/lib/libradius/libradius.c
will break the stack so that mpd gets segfault in FreeBSD 4.7-RELEASE-p3,
but I can't figure out where it does.

If somebody want the core file, I can mail him.

I copied rad_send_request() into mpd's radius.c last week, and it worked
fine.  I attach my patch file in this mail.

On Mon, Mar 03, 2003 at 10:46:05AM +0100, Michael Bretterklieber wrote:
> Hi,
> 
> Vincent Jardin schrieb:
> >1/ When Radius is used with mpd and the answer delay of the Radius server 
> >is high, how can some PAP or CHAP timeout be avoided ?
> >
> you mean, that the client times out during authentication saying that 
> the server didn't responded?
> 
> A known issue is that mpd is blocked during RADIUS requests, the 
> solution will be to change from rad_send_request(); to 
> rad_init_send_request() and rad_continue_send_request(); to avoid 
> blocking of mpd.
> 
> I have this on my todo-list, but atm it has low prio.
> 
> bye,

-- 
* Gea-Suan Lin  (public key: http://ccreader.nctu.edu.tw/~gslin/key.txt)
* If you cannot convince them, confuse them.           -- Harry S Truman
--- /usr/ports/net/mpd/work/mpd-3.12/src/radius.c       Tue Feb 11 06:21:15 2003
+++ radius.c    Mon Mar  3 17:48:47 2003
@@ -152,10 +152,10 @@
     return 0;
 }
 
-void RadiusInit(void) {
+static void
+RadiusInit(void) {
   struct radius *rad = &bund->radius;
 
-  if (rad->radh != NULL) rad_close(rad->radh);
   memset(rad, 0, sizeof(struct radius) - sizeof(struct radiusconf));
 }
 
@@ -209,6 +209,7 @@
 
   if (rad_create_request(rad->radh, RAD_ACCESS_REQUEST) == -1) {
     Log(LG_RADIUS, ("[%s] RADIUS: rad_create_request: %s", lnk->name, 
rad_strerror(rad->radh)));
+    rad_close(rad->radh);
     return (RAD_NACK);
   }
 
@@ -343,37 +344,86 @@
     }
   }
 
-  switch (rad_send_request(rad->radh)) {
+  Log(LG_RADIUS, ("[%s] RADIUS: %s: XXX 1 name=%s passlen=%d challenge_size=%d 
chapid=%d auth_type=%d", lnk->name, function, name, passlen, challenge_size, chapid, 
auth_type));
 
-    case RAD_ACCESS_ACCEPT:
-      rad->valid = 1;
-      Log(LG_RADIUS, ("[%s] RADIUS: %s: RAD_ACCESS_ACCEPT for user %s", lnk->name, 
function, name));
-      break;
+  {
+    struct timeval timelimit;
+    struct timeval tv;
+    int fd;
+    int n;
 
-    case RAD_ACCESS_REJECT:
-      Log(LG_RADIUS, ("[%s] RADIUS: %s: RAD_ACCESS_REJECT for user %s", lnk->name, 
function, name));
-      rad_close(rad->radh);
-      return(RAD_NACK);
-      break;
+    n = rad_init_send_request(rad->radh, &fd, &tv);
 
-    case -1:
-      Log(LG_RADIUS, ("[%s] RADIUS: %s: rad_send_request failed %s", lnk->name,
-      function, rad_strerror(rad->radh)));
-      return(RAD_NACK);
-      break;
-    default:
-      Log(LG_RADIUS, ("[%s] RADIUS: %s: rad_send_request: unexpected "
-      "return value %s", lnk->name, function, rad_strerror(rad->radh)));
-      rad_close(rad->radh);
-      return(RAD_NACK);
+    if (n != 0)
+      return n;
+
+    gettimeofday(&timelimit, NULL);
+    timeradd(&tv, &timelimit, &timelimit);
+
+    for ( ; ; ) {
+      fd_set readfds;
+
+      FD_ZERO(&readfds);
+      FD_SET(fd, &readfds);
+
+      n = select(fd + 1, &readfds, NULL, NULL, &tv);
+
+      if (n == -1)
+       break;
+
+      if (!FD_ISSET(fd, &readfds)) {
+       /* Compute a new timeout */
+       gettimeofday(&tv, NULL);
+       timersub(&timelimit, &tv, &tv);
+       if (tv.tv_sec > 0 || (tv.tv_sec == 0 && tv.tv_usec > 0))
+         /* Continue the select */
+         continue;
+      }
+
+      Log(LG_RADIUS, ("[%s] RADIUS: %s: XXX 1 %s Host:%s PeerIp: %s", lnk->name, 
function, name, host, peeripname));
+      n = rad_continue_send_request(rad->radh, n, &fd, &tv);
+      Log(LG_RADIUS, ("[%s] RADIUS: %s: XXX 2 %s Host:%s PeerIp: %s", lnk->name, 
function, name, host, peeripname));
+
+      if (n != 0)
+       break;
+
+      gettimeofday(&timelimit, NULL);
+      timeradd(&tv, &timelimit, &timelimit);
     }
 
-    // Remember authname
-    strncpy(rad->authname, name, AUTH_MAX_AUTHNAME);
-    res = RadiusGetParams();
-    if (res == RAD_NACK) rad->valid = 0;
-    rad_close(rad->radh);
-    return(res);
+    switch (n) {
+
+      case RAD_ACCESS_ACCEPT:
+       rad->valid = 1;
+       Log(LG_RADIUS, ("[%s] RADIUS: %s: RAD_ACCESS_ACCEPT for user %s", lnk->name, 
function, name));
+       break;
+
+      case RAD_ACCESS_REJECT:
+       Log(LG_RADIUS, ("[%s] RADIUS: %s: RAD_ACCESS_REJECT for user %s", lnk->name, 
function, name));
+       rad_close(rad->radh);
+       return(RAD_NACK);
+       break;
+
+      case -1:
+       Log(LG_RADIUS, ("[%s] RADIUS: %s: rad_send_request failed %s", lnk->name,
+       function, rad_strerror(rad->radh)));
+       return(RAD_NACK);
+       break;
+
+      default:
+       Log(LG_RADIUS, ("[%s] RADIUS: %s: rad_send_request: unexpected "
+       "return value %s", lnk->name, function, rad_strerror(rad->radh)));
+       rad_close(rad->radh);
+       return(RAD_NACK);
+    }
+  }
+
+  // Remember authname
+  strncpy(rad->authname, name, AUTH_MAX_AUTHNAME);
+  res = RadiusGetParams();
+  if (res == RAD_NACK) rad->valid = 0;
+  rad_close(rad->radh);
+  return(res);
 }
 
 int

Reply via email to