[PATCH] per-server retry option for pam_radius_auth

Robert Varga nite at hq.alert.sk
Wed Sep 19 23:06:02 CEST 2007


Hi,

the attached patch (against 1.3.17) allows the administrator to configure
retries on a per-server basis in /etc/raddb/server. If the retry field
is not specified, it will revert to using whatever number was specified
as retry= parameter.

Also, it seems that the description of retry= parameter in USAGE is not
entirely correct, as retry controls the number retries for each server
configured. The patch corrects that piece of documentation, too.

Please consider inclusion of this patch.

-- 
Bye,
Robert Varga

Reality continues to ruin my life. -- Calvin
-------------- next part --------------
diff -urN pam_radius-1.3.17/USAGE pam_radius-1.3.17-retry/USAGE
--- pam_radius-1.3.17/USAGE	2007-03-26 07:35:31.000000000 +0200
+++ pam_radius-1.3.17-retry/USAGE	2007-09-19 01:36:34.613667651 +0200
@@ -62,8 +62,10 @@
                  This feature may be disabled by using 'client_id='.
                  i.e. A blank client ID.
 
-retry = #      - allow a number of retries before continuing to the next
-                 authentication module
+retry = #      - allow a number of authentication retries before continuing
+                 to the next configured server. This parameter acts as
+		 the default when no (or invalid) server-specific retry is
+		 configured.
 
 use_authtok    - force the use of a previously entered password.
                  This is  needed for pluggable password strength checking
diff -urN pam_radius-1.3.17/pam_radius_auth.c pam_radius-1.3.17-retry/pam_radius_auth.c
--- pam_radius-1.3.17/pam_radius_auth.c	2007-03-26 11:36:13.000000000 +0200
+++ pam_radius-1.3.17-retry/pam_radius_auth.c	2007-09-19 01:19:27.001035047 +0200
@@ -592,6 +592,7 @@
   struct sockaddr_in * s_in;
   int timeout;
   int line = 0;
+  int retries;
 
   /* the first time around, read the configuration file */
   if ((fserver = fopen (conf_file, "r")) == (FILE*)NULL) {
@@ -621,7 +622,8 @@
     }
     
     timeout = 3;
-    if (sscanf(p, "%s %s %d", hostname, secret, &timeout) < 2) {
+    retries = -1;
+    if (sscanf(p, "%s %s %d %d", hostname, secret, &timeout, &retries) < 2) {
       _pam_log(LOG_ERR, "ERROR reading %s, line %d: Could not read hostname or secret\n",
 	       conf_file, line);
       continue; /* invalid line */
@@ -648,6 +650,12 @@
       } else {
 	server->timeout = timeout;
       }
+
+      if ((retries < 0) || (retries > 10)) {
+        retries = conf->retries;
+      }
+      server->retries = retries;
+
       server->next = NULL;
     }
   }
@@ -764,7 +772,7 @@
  */
 static int
 talk_radius(radius_conf_t *conf, AUTH_HDR *request, AUTH_HDR *response,
-            char *password, char *old_password, int tries)
+            char *password, char *old_password, int do_retry)
 {
   int salen, total_length;
   fd_set set;
@@ -814,7 +822,10 @@
       get_accounting_vector(request, server);
     }
 
-    server_tries = tries;
+    server_tries = 1;
+    if (do_retry) {
+      server_tries += server->retries;
+    }
 send:
     /* send the packet */
     if (sendto(conf->sockfd, (char *) request, total_length, 0,
@@ -1175,7 +1186,7 @@
   DPRINT(LOG_DEBUG, "Sending RADIUS request code %d", request->code);
 
   retval = talk_radius(&config, request, response, password,
-                       NULL, config.retries + 1);
+                       NULL, 1);
   PAM_FAIL_CHECK;
 
   DPRINT(LOG_DEBUG, "Got RADIUS response code %d", response->code);
@@ -1223,7 +1234,7 @@
     /* copy the state over from the servers response */
     add_attribute(request, PW_STATE, a_state->data, a_state->length - 2);
 
-    retval = talk_radius(&config, request, response, resp2challenge, NULL, 1);
+    retval = talk_radius(&config, request, response, resp2challenge, NULL, 0);
     PAM_FAIL_CHECK;
 
     DPRINT(LOG_DEBUG, "Got response to challenge code %d", response->code);
@@ -1347,7 +1358,7 @@
     add_int_attribute(request, PW_ACCT_SESSION_TIME, time(NULL) - session_time);
   }
 
-  retval = talk_radius(&config, request, response, NULL, NULL, 1);
+  retval = talk_radius(&config, request, response, NULL, NULL, 0);
   PAM_FAIL_CHECK;
 
   /* oops! They don't have the right password.  Complain and die. */
@@ -1466,7 +1477,7 @@
     build_radius_packet(request, user, password, &config);
     add_int_attribute(request, PW_USER_SERVICE_TYPE, PW_AUTHENTICATE_ONLY);
     
-    retval = talk_radius(&config, request, response, password, NULL, 1);
+    retval = talk_radius(&config, request, response, password, NULL, 0);
     PAM_FAIL_CHECK;
 
     /* oops! They don't have the right password.  Complain and die. */
@@ -1569,7 +1580,7 @@
     build_radius_packet(request, user, new_password, &config);
     add_password(request, PW_OLD_PASSWORD, password, password);
     
-    retval = talk_radius(&config, request, response, new_password, password, 1);
+    retval = talk_radius(&config, request, response, new_password, password, 0);
     PAM_FAIL_CHECK;
 
     /* Whew! Done password changing, check for password acknowledge */
diff -urN pam_radius-1.3.17/pam_radius_auth.conf pam_radius-1.3.17-retry/pam_radius_auth.conf
--- pam_radius-1.3.17/pam_radius_auth.conf	2000-07-10 21:18:42.000000000 +0200
+++ pam_radius-1.3.17-retry/pam_radius_auth.conf	2007-09-19 01:19:27.011673047 +0200
@@ -8,7 +8,7 @@
 #  lines.  Blank lines or lines beginning with '#' are treated as
 #  comments, and are ignored.  The fields are:
 #
-#  server[:port] secret [timeout]
+#  server[:port] secret [timeout] [retries]
 #
 #  the port name or number is optional.  The default port name is
 #  "radius", and is looked up from /etc/services The timeout field is
@@ -22,9 +22,13 @@
 #  The timeout field controls how many seconds the module waits before
 #  deciding that the server has failed to respond.
 #
-# server[:port]	shared_secret      timeout (s)
-127.0.0.1	secret             1
-other-server    other-secret       3
+#  The retries field indicates how many time the server should be retried
+#  before continuing to other servers. Valid values range from 0 to 10,
+#  other values are overridden by the retry= parameter.
+#
+# server[:port]	shared_secret      timeout (s)	retries
+127.0.0.1	secret             1		0
+other-server    other-secret       3		3
 
 #
 # having localhost in your radius configuration is a Good Thing.
diff -urN pam_radius-1.3.17/pam_radius_auth.h pam_radius-1.3.17-retry/pam_radius_auth.h
--- pam_radius-1.3.17/pam_radius_auth.h	2007-03-26 07:35:31.000000000 +0200
+++ pam_radius-1.3.17-retry/pam_radius_auth.h	2007-09-19 01:19:27.023667997 +0200
@@ -42,6 +42,7 @@
   char *secret;
   int timeout;
   int accounting;
+  int retries;
 } radius_server_t;
 
 typedef struct radius_conf_t {


More information about the Freeradius-Devel mailing list