]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/plugins/radius/radius.c
Check for vendor code before trying to interpret RADIUS attributes.
[ppp.git] / pppd / plugins / radius / radius.c
index 3dc69aeae92b2a2b42d97fed65afcf8e8af2d052..fa638d0327d4fced1d478aba858d1d3515673bea 100644 (file)
@@ -21,7 +21,7 @@
 *
 ***********************************************************************/
 static char const RCSID[] =
-"$Id: radius.c,v 1.2 2002/02/08 17:28:31 dfs Exp $";
+"$Id: radius.c,v 1.4 2002/03/01 15:16:51 dfs Exp $";
 
 #include "pppd.h"
 #include "chap.h"
@@ -61,9 +61,6 @@ static int radius_init(char *msg);
 static int get_client_port(char *ifname);
 static int radius_allowed_address(u_int32_t addr);
 
-void (*radius_attributes_hook)(VALUE_PAIR *) = NULL;
-void (*radius_pre_auth_hook)(char const *user) = NULL;
-
 #ifndef MAXSESSIONID
 #define MAXSESSIONID 32
 #endif
@@ -80,8 +77,18 @@ struct radius_state {
     char config_file[MAXPATHLEN];
     char session_id[MAXSESSIONID + 1];
     time_t start_time;
+    SERVER *authserver;                /* Authentication server to use */
+    SERVER *acctserver;                /* Accounting server to use */
 };
 
+void (*radius_attributes_hook)(VALUE_PAIR *) = NULL;
+
+/* The pre_auth_hook MAY set authserver and acctserver if it wants.
+   In that case, they override the values in the radiusclient.conf file */
+void (*radius_pre_auth_hook)(char const *user,
+                            SERVER **authserver,
+                            SERVER **acctserver) = NULL;
+
 static struct radius_state rstate;
 
 char pppd_version[] = VERSION;
@@ -189,7 +196,9 @@ radius_pap_auth(char *user,
     make_username_realm(user);
 
     if (radius_pre_auth_hook) {
-       radius_pre_auth_hook(rstate.user);
+       radius_pre_auth_hook(rstate.user,
+                            &rstate.authserver,
+                            &rstate.acctserver);
     }
 
     send = NULL;
@@ -212,7 +221,13 @@ radius_pap_auth(char *user,
                       VENDOR_NONE);
     }
 
-    result = rc_auth(rstate.client_port, send, &received, radius_msg);
+    if (rstate.authserver) {
+       result = rc_auth_using_server(rstate.authserver,
+                                     rstate.client_port, send,
+                                     &received, radius_msg);
+    } else {
+       result = rc_auth(rstate.client_port, send, &received, radius_msg);
+    }
 
     if (result == OK_RC) {
        if (radius_setparams(received, radius_msg) < 0) {
@@ -268,7 +283,9 @@ radius_chap_auth(char *user,
        make_username_realm(user);
        rstate.client_port = get_client_port (ifname);
        if (radius_pre_auth_hook) {
-           radius_pre_auth_hook(rstate.user);
+           radius_pre_auth_hook(rstate.user,
+                                &rstate.authserver,
+                                &rstate.acctserver);
        }
     }
 
@@ -298,7 +315,13 @@ radius_chap_auth(char *user,
      * make authentication with RADIUS server
      */
 
-    result = rc_auth (rstate.client_port, send, &received, radius_msg);
+    if (rstate.authserver) {
+       result = rc_auth_using_server(rstate.authserver,
+                                     rstate.client_port, send,
+                                     &received, radius_msg);
+    } else {
+       result = rc_auth(rstate.client_port, send, &received, radius_msg);
+    }
 
     if (result == OK_RC) {
        if (!rstate.done_chap_once) {
@@ -374,44 +397,46 @@ radius_setparams(VALUE_PAIR *vp, char *msg)
      */
 
     while (vp) {
-       switch (vp->attribute) {
-       case PW_SERVICE_TYPE:
-           /* check for service type       */
-           /* if not FRAMED then exit      */
-           if (vp->lvalue != PW_FRAMED) {
-               slprintf(msg, BUF_LEN, "RADIUS: wrong service type %ld for %s",
-                        vp->lvalue, rstate.user);
-               return -1;
-           }
-           break;
-       case PW_FRAMED_PROTOCOL:
-           /* check for framed protocol type       */
-           /* if not PPP then also exit            */
-           if (vp->lvalue != PW_PPP) {
-               slprintf(msg, BUF_LEN, "RADIUS: wrong framed protocol %ld for %s",
-                        vp->lvalue, rstate.user);
-               return -1;
-           }
-           break;
-
-       case PW_FRAMED_IP_ADDRESS:
-           /* seting up remote IP addresses */
-           remote = vp->lvalue;
-           if (remote == 0xffffffff) {
-               /* 0xffffffff means user should be allowed to select one */
-               rstate.any_ip_addr_ok = 1;
-           } else if (remote != 0xfffffffe) {
-               /* 0xfffffffe means NAS should select an ip address */
-               remote = htonl(vp->lvalue);
-               if (bad_ip_adrs (remote)) {
-                   slprintf(msg, BUF_LEN, "RADIUS: bad remote IP address %I for %s",
-                            remote, rstate.user);
+       if (vp->vendorcode == VENDOR_NONE) {
+           switch (vp->attribute) {
+           case PW_SERVICE_TYPE:
+               /* check for service type       */
+               /* if not FRAMED then exit      */
+               if (vp->lvalue != PW_FRAMED) {
+                   slprintf(msg, BUF_LEN, "RADIUS: wrong service type %ld for %s",
+                            vp->lvalue, rstate.user);
                    return -1;
                }
-               rstate.choose_ip = 1;
-               rstate.ip_addr = remote;
-           }
+               break;
+           case PW_FRAMED_PROTOCOL:
+               /* check for framed protocol type       */
+               /* if not PPP then also exit            */
+               if (vp->lvalue != PW_PPP) {
+                   slprintf(msg, BUF_LEN, "RADIUS: wrong framed protocol %ld for %s",
+                            vp->lvalue, rstate.user);
+                   return -1;
+               }
+               break;
+
+           case PW_FRAMED_IP_ADDRESS:
+               /* seting up remote IP addresses */
+               remote = vp->lvalue;
+               if (remote == 0xffffffff) {
+                   /* 0xffffffff means user should be allowed to select one */
+                   rstate.any_ip_addr_ok = 1;
+               } else if (remote != 0xfffffffe) {
+                   /* 0xfffffffe means NAS should select an ip address */
+                   remote = htonl(vp->lvalue);
+                   if (bad_ip_adrs (remote)) {
+                       slprintf(msg, BUF_LEN, "RADIUS: bad remote IP address %I for %s",
+                                remote, rstate.user);
+                       return -1;
+                   }
+                   rstate.choose_ip = 1;
+                   rstate.ip_addr = remote;
+               }
            break;
+           }
        }
        vp = vp->next;
     }
@@ -474,7 +499,12 @@ radius_acct_start(void)
     av_type = htonl(hisaddr);
     rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
 
-    result = rc_acct(rstate.client_port, send);
+    if (rstate.acctserver) {
+       result = rc_acct_using_server(rstate.acctserver,
+                                     rstate.client_port, send);
+    } else {
+       result = rc_acct(rstate.client_port, send);
+    }
 
     rc_avpair_free(send);
 
@@ -561,7 +591,13 @@ radius_acct_stop(void)
     av_type = htonl(hisaddr);
     rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
 
-    result = rc_acct(rstate.client_port, send);
+    if (rstate.acctserver) {
+       result = rc_acct_using_server(rstate.acctserver,
+                                     rstate.client_port, send);
+    } else {
+       result = rc_acct(rstate.client_port, send);
+    }
+
     if (result != OK_RC) {
        /* RADIUS server could be down so make this a warning */
        syslog(LOG_WARNING,
@@ -699,4 +735,3 @@ char *radius_logged_in_user(void)
 {
     return rstate.user;
 }
-