help-gnu-radius
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-gnu-radius] Failthru proxying?


From: Sergey Poznyakoff
Subject: Re: [Help-gnu-radius] Failthru proxying?
Date: Tue, 09 Jul 2002 13:14:28 +0300

> I was searching something like that but I didn't find anything.
> So I thought that a feature like in tacacs  - 
>     IF user_not_fount THEN do
>             stay quiet (do not send reject nor ack ...)
> will help, having 2 or more radius server configured on NAS-es

Well, this can be done. The following patch introduces a new
authentication type Ignore. To obtain the desired behaviour,
add the following entry to the end of your raddb/users:

DEFAULT Auth-Type = Ignore
        NULL

The patch is agains version 0.96.3. It includes all improvements
discussed in the list so far. When configuring the patched version
use --enable-maintainer-mode option to configure.

Regards,
Sergey
==============================================================================
Index: ChangeLog
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/ChangeLog 
/home/gray/radius-0.96-series/ChangeLog
--- /home/gray/tmp/gnu-radius-0.96.3/ChangeLog  Wed Jun  5 14:40:28 2002
+++ /home/gray/radius-0.96-series/ChangeLog     Fri Jul  5 15:00:37 2002
@@ -1,3 +1,43 @@
+2002-07-05  Sergey Poznyakoff 
+
+       * radiusd/auth.c (sfn_validate): Synchronized with the
+         main trunc.
+
+2002-07-05  Sergey Poznyakoff 
+
+       * radiusd/acct.c (rad_accounting): Bugfix. The reply value
+         was not used. Thanks to Michael Samuel.
+
+2002-07-02  Sergey Poznyakoff 
+
+       * radiusd/radius.c (radrecv): Add NAS-IP-Address to the packet
+         if the NAS didn't supply one.
+       * radiusd/auth.c (sfn_validate): Bugfix: the return from
+         check_expiration() was handled incorrectly.
+       * raddb/dictionary (Expiration): Fixed properties.
+       * THANKS: Added Cornel Cristea
+
+       * test/radiusd.m4: Added tests for Expiration attribute.
+       * test/raddb/users.in: Likewise.
+       
+2002-06-20  Sergey Poznyakoff
+
+       * configure.in: YACC_OPTS are always -t.
+       * radiusd/config.y (channel_stmt production): bugfix (sync'ed
+         with the main trunc).
+
+       * radiusd/rewrite.y: New statement: `delete'. New notation:
+         %[attr](n). 
+       * doc/texinfo/extensions.texi: Documented `delete' statement
+         and %[attr](n) notation.
+       * radlib/avl.c: (avl_find_n, avl_delete_n): New functions.  
+       * include/radius.h (avl_find_n, avl_delete_n): New functions.  
+       * mibs/GNU-RADIUS-STAT-MIB.txt: Fixed revision syntax
+
+2002-06-05  Sergey Poznyakoff
+
+       -= Version 0.96.3 released =-
+       
 2002-06-05  Sergey Poznyakoff  
 
        * TODO: Updated. Lots of entries were already implemented in 1.0,
Index: doc/texinfo/extensions.texi
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/doc/texinfo/extensions.texi 
/home/gray/radius-0.96-series/doc/texinfo/extensions.texi
--- /home/gray/tmp/gnu-radius-0.96.3/doc/texinfo/extensions.texi        Tue Mar 
19 16:31:59 2002
+++ /home/gray/radius-0.96-series/doc/texinfo/extensions.texi   Thu Jun 20 
15:09:49 2002
@@ -579,12 +579,28 @@ whose entries can be accessed using the 
 
 @example
 @samp{%[} @var{attribute-name} @samp{]}
address@hidden @var{attribute-name} @samp{]} @samp{(} @var{n} @samp{)}
 @end example
 
 @noindent
-Thus notation returns the value of the attribute @var{attribute-name}.
+The first notation returns the value of the attribute @var{attribute-name}.
 @var{attribute-name} should be a valid Radius dictionary name
 (@pxref{dictionary file}).
+
+The second notation returns the value of the @var{n}th attribute of type
address@hidden . Index @var{n} is counted from zero, so
+
address@hidden
+        address@hidden(0)
address@hidden example
+
address@hidden
+is equivalent to
+
address@hidden
+        address@hidden
address@hidden example
+
 @item Identifiers
 Identifiers represent functions and variables. These are described in
 the next section.
@@ -701,6 +717,7 @@ An @dfn{expression} is:
 @item A boolean expression
 @item An assignment
 @item A function call
address@hidden A delete statement
 @end itemize
 
 @subheading Type coercion
@@ -763,6 +780,20 @@ function.
 @emph{Please note} that, unlike in C, the mismatch between the
 number of actual arguments and number of formal parameters in the
 compiled function declaration is not an error but rather a warning.
+
address@hidden Delete statement
+
+The @samp{delete} statement is used to delete an attribute or attributes
+from the incoming request. Its syntax is:
+
address@hidden
+delete @var{attribute-name};
+delete @var{attribute-name}(@var{n});
address@hidden example
+
+The first variant deletes @emph{all} the atributes of the given type.
+The second variant deletes only @var{n}th occurrence of the matching
+attribute.
 
 @comment **L4***************************************************************
 @node Built-in Functions
Index: include/radius.h
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/include/radius.h 
/home/gray/radius-0.96-series/include/radius.h
--- /home/gray/tmp/gnu-radius-0.96.3/include/radius.h   Thu May 30 16:43:19 2002
+++ /home/gray/radius-0.96-series/include/radius.h      Thu Jun 20 12:51:29 2002
@@ -261,7 +261,9 @@ VALUE_PAIR *avp_alloc();
 void avp_free();
 void avl_free(VALUE_PAIR *);
 VALUE_PAIR *avl_find(VALUE_PAIR *, int);
+VALUE_PAIR *avl_find_n(VALUE_PAIR *, int, int);
 void avl_delete(VALUE_PAIR **, int);
+void avl_delete_n(VALUE_PAIR **first, int attr, int n);
 void avl_add_list(VALUE_PAIR **, VALUE_PAIR *);
 void avl_add_pair(VALUE_PAIR **, VALUE_PAIR *);
 VALUE_PAIR *avl_dup(VALUE_PAIR *from);
Index: include/radiusd.h
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/include/radiusd.h 
/home/gray/radius-0.96-series/include/radiusd.h
--- /home/gray/tmp/gnu-radius-0.96.3/include/radiusd.h  Tue Mar 19 16:32:00 2002
+++ /home/gray/radius-0.96-series/include/radiusd.h     Tue Jul  9 12:28:05 2002
@@ -201,6 +201,7 @@ void snmp_req_drop(int type, SNMP_REQ *r
 #define AUTH_FAIL    1 /* Password fail */
 #define AUTH_NOUSER  2 /* No such user  */
 #define AUTH_REJECT  3 /* Rejected */
+#define AUTH_IGNORE  4 /* Ignored */
 
 /* Logging modes */
 #define RLOG_AUTH               0x0001
Index: raddb/dictionary
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/raddb/dictionary 
/home/gray/radius-0.96-series/raddb/dictionary
--- /home/gray/tmp/gnu-radius-0.96.3/raddb/dictionary   Tue Mar 19 16:32:00 2002
+++ /home/gray/radius-0.96-series/raddb/dictionary      Tue Jul  9 12:26:26 2002
@@ -1,5 +1,5 @@
 #
-# $Id: dictionary,v 1.24 2001/12/21 11:13:02 gray Exp $
+# $Id: dictionary,v 1.24.2.1 2002/07/02 20:54:28 gray Exp $
 #
 
 ## NOTE: Beside its usual functions this file also serves as a source
@@ -140,7 +140,7 @@ ATTRIBUTE   Password-Expire-Days    2145    inte
 # Non-Protocol Attributes
 # These attributes are used internally by the server
 #
-ATTRIBUTE      Expiration                21    date    - [------]
+ATTRIBUTE      Expiration                21    date    - [L-----]
 ATTRIBUTE      Auth-Type               1000    integer - [L--R-R]      
 ATTRIBUTE      Menu                    1001    string  - [-R----]=
 ATTRIBUTE      Termination-Menu        1002    string  - [-R----]=
@@ -251,6 +251,7 @@ VALUE               Auth-Type               System          
        1
 VALUE          Auth-Type               SecurID                 2
 VALUE          Auth-Type               Crypt-Local             3
 VALUE          Auth-Type               Reject                  4
+VALUE          Auth-Type               Ignore                  5
 
 #
 # Extensions introduced by Cistron
Index: radiusd/acct.c
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/radiusd/acct.c 
/home/gray/radius-0.96-series/radiusd/acct.c
--- /home/gray/tmp/gnu-radius-0.96.3/radiusd/acct.c     Thu May 30 17:06:15 2002
+++ /home/gray/radius-0.96-series/radiusd/acct.c        Fri Jul  5 14:45:42 2002
@@ -19,7 +19,7 @@
 
 #ifndef lint
 static char rcsid[] =
-"@(#) $Id: acct.c,v 1.28.2.2 2002/05/30 14:06:15 gray Exp $";
+"@(#) $Id: acct.c,v 1.28.2.3 2002/07/05 11:45:42 gray Exp $";
 #endif
 #define LOG_EMPTY_USERNAME
 
@@ -622,7 +622,7 @@ rad_accounting(radreq, activefd)
                write_detail(radreq, auth, "detail");
                avl_move_attr(&reply, &radreq->request, DA_PROXY_STATE); 
                rad_send_reply(RT_ASCEND_EVENT_RESPONSE,
-                              radreq, NULL, NULL, activefd);
+                              radreq, reply, NULL, activefd);
                avl_move_attr(&radreq->request, &reply, DA_PROXY_STATE);
                stat_inc(acct, radreq->ipaddr, num_resp);
                return 0;
@@ -635,7 +635,7 @@ rad_accounting(radreq, activefd)
                VALUE_PAIR *reply = NULL;
                avl_move_attr(&reply, &radreq->request, DA_PROXY_STATE);
                rad_send_reply(RT_ACCOUNTING_RESPONSE,
-                              radreq, NULL, NULL, activefd);
+                              radreq, reply, NULL, activefd);
                avl_move_attr(&radreq->request, &reply, DA_PROXY_STATE);
                stat_inc(acct, radreq->ipaddr, num_resp);
                return 0;
Index: radiusd/auth.c
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/radiusd/auth.c 
/home/gray/radius-0.96-series/radiusd/auth.c
--- /home/gray/tmp/gnu-radius-0.96.3/radiusd/auth.c     Thu May 30 17:06:41 2002
+++ /home/gray/radius-0.96-series/radiusd/auth.c        Tue Jul  9 12:27:44 2002
@@ -18,7 +18,7 @@
 #define RADIUS_MODULE_AUTH_C
 #ifndef lint
 static char rcsid[] =
-"@(#) $Id: auth.c,v 1.47.2.2 2002/05/30 14:06:41 gray Exp $";
+"@(#) $Id: auth.c,v 1.47.2.4 2002/07/05 11:58:18 gray Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -218,7 +218,7 @@ unix_pass(name, passwd)
  *                     AUTH_FAIL    Password fail
  *                      AUTH_NOUSER  No such user 
  *                     AUTH_REJECT  Rejected
- *                     
+ *                     AUTH_IGNORE  Silently Ignored
  */
 int
 rad_check_password(radreq, check_item, namepair, user_msg, userpass)
@@ -247,12 +247,17 @@ rad_check_password(radreq, check_item, n
        if ((tmp = avl_find(check_item, DA_AUTH_TYPE)) != NULL)
                auth_type = tmp->lvalue;
 
-       if (auth_type == DV_AUTH_TYPE_ACCEPT)
+       switch (auth_type) {
+       case DV_AUTH_TYPE_ACCEPT:
                return AUTH_OK;
 
-       if (auth_type == DV_AUTH_TYPE_REJECT) 
+       case DV_AUTH_TYPE_REJECT:
                return AUTH_REJECT;
 
+       case DV_AUTH_TYPE_IGNORE:
+               return AUTH_IGNORE;
+       }
+
        /* Find the password sent by the user. If it's not present,
           authentication fails. */
        
@@ -938,56 +943,58 @@ sfn_validate(m)
        RADIUS_REQ *radreq = m->req;
        int rc;
        
-       /*
-        * Validate the user
-        */
-       if ((rc = check_expiration(m)) >= 0) {
-               rc = rad_check_password(radreq,
-                                       m->user_check, m->namepair,
-                                       &m->user_msg,
-                                       m->userpass);
-
-               if (rc != AUTH_OK) { 
-                       stat_inc(auth, radreq->ipaddr, num_rejects);
-                       newstate(as_reject);
-                       auth_format_msg(m, MSG_ACCESS_DENIED);
+       avl_move_attr(&m->user_reply, &m->proxy_pairs, DA_PROXY_STATE);
+       rc = rad_check_password(radreq,
+                               m->user_check, m->namepair,
+                               &m->user_msg,
+                               m->userpass);
+       if (rc != AUTH_OK) {
+               stat_inc(auth, radreq->ipaddr, num_rejects);
 
-                       if (is_log_mode(m, RLOG_AUTH)) {
-                               switch (rc) {
-                               case AUTH_REJECT:
-                                       auth_log(m, _("Rejected"),
-                                                NULL, NULL, NULL);  
-                                       return;
+               if (is_log_mode(m, RLOG_AUTH)) {
+                       switch (rc) {
+                       case AUTH_IGNORE:
+                               auth_log(m, _("Ignored"),
+                                        NULL, NULL, NULL);
+                               newstate(as_stop);
+                               return;
                                
-                               case AUTH_NOUSER:
-                                       auth_log(m, _("Invalid user"),
-                                                NULL, NULL, NULL);
-                                       return;
+                       case AUTH_REJECT:
+                               auth_log(m, _("Rejected"),
+                                        NULL, NULL, NULL);  
+                               break;
                                
-                               case AUTH_FAIL:
-                                       break;
-                               }
-                       }
-               }               
-              /*if (p = avl_find(m->user_reply, DA_REPLY_MESSAGE))
-                       m->user_msg = dup_string(p->strvalue);*/
-       }
-
-       avl_move_attr(&m->user_reply, &m->proxy_pairs, DA_PROXY_STATE);
+                       case AUTH_NOUSER:
+                               auth_log(m, _("Invalid user"),
+                                        NULL, NULL, NULL);
+                               break;
+                               
+                       case AUTH_FAIL:
+                               auth_log(m,
+                                        _("Login incorrect"),
+                                        is_log_mode(m, RLOG_FAILED_PASS) ?
+                                        m->userpass : NULL,
+                                        NULL, NULL);
+                               break;
 
-       if (rc != AUTH_OK) {
-               /*
-                * Failed to validate the user.
-                */
-               newstate(as_reject);
-               if (is_log_mode(m, RLOG_AUTH)) {
-                       auth_log(m,
-                                _("Login incorrect"),
-                                is_log_mode(m, RLOG_FAILED_PASS) ?
-                                                      m->userpass : NULL,
-                                NULL, NULL);
+                       default:
+                               insist_fail("sfn_validate");
+                       }
                }
+               newstate(as_reject);
+               auth_format_msg(m, MSG_ACCESS_DENIED);
        }
+
+       if (check_expiration(m) != AUTH_OK) {
+                newstate(as_reject);
+                if (is_log_mode(m, RLOG_AUTH)) {
+                        auth_log(m,
+                                 _("Login incorrect"),
+                                 is_log_mode(m, RLOG_FAILED_PASS) ?
+                                m->userpass : NULL,
+                                 _("Password expired"), "");
+                }
+        }
 }
 
 void
Index: radiusd/config.y
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/radiusd/config.y 
/home/gray/radius-0.96-series/radiusd/config.y
--- /home/gray/tmp/gnu-radius-0.96.3/radiusd/config.y   Tue Mar 19 17:10:18 2002
+++ /home/gray/radius-0.96-series/radiusd/config.y      Thu Jun 20 16:40:30 2002
@@ -18,7 +18,7 @@
 
 #ifndef lint
 static char rcsid[] = 
-       "@(#) $Id: config.y,v 1.30.2.1 2002/03/19 15:10:18 gray Exp $";
+       "@(#) $Id: config.y,v 1.30.2.2 2002/06/20 13:40:30 gray Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -470,6 +470,7 @@ channel_stmt    : T_CHANNEL channel_name
 channel_name    : { expect_string = 1; } T_STRING
                   {
                          expect_string = 0;
+                         memset(&channel, 0, sizeof(channel));
                          channel.mode = LM_UNKNOWN;
                          strcpy($$, $2);
                  }
Index: radiusd/radius.c
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/radiusd/radius.c 
/home/gray/radius-0.96-series/radiusd/radius.c
--- /home/gray/tmp/gnu-radius-0.96.3/radiusd/radius.c   Tue Mar 19 16:32:00 2002
+++ /home/gray/radius-0.96-series/radiusd/radius.c      Tue Jul  2 23:54:53 2002
@@ -18,7 +18,7 @@
 #define RADIUS_MODULE_RADIUS_C
 #ifndef lint
 static char rcsid[] =
-"@(#) $Id: radius.c,v 1.20 2001/12/19 14:05:08 gray Exp $";
+"@(#) $Id: radius.c,v 1.20.2.1 2002/07/02 20:54:53 gray Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -473,6 +473,12 @@ radrecv(host, udp_port, buffer, length)
                }
                ptr += attrlen;
                length -= attrlen;
+       }
+       if (!avl_find(first_pair, DA_NAS_IP_ADDRESS)) {
+               pair =  avp_create(DA_NAS_IP_ADDRESS,
+                                   0, NULL,
+                                   host);
+               avl_add_pair(&first_pair, pair);
        }
        radreq->request = first_pair;
        return(radreq);
Index: radiusd/rewrite.y
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/radiusd/rewrite.y 
/home/gray/radius-0.96-series/radiusd/rewrite.y
--- /home/gray/tmp/gnu-radius-0.96.3/radiusd/rewrite.y  Tue Mar 19 16:32:00 2002
+++ /home/gray/radius-0.96-series/radiusd/rewrite.y     Thu Jun 20 16:41:20 2002
@@ -38,7 +38,7 @@
         
 #ifndef lint
 static char rcsid[] =
-  "@(#) $Id: rewrite.y,v 1.27 2001/12/19 14:02:18 gray Exp $";
+  "@(#) $Id: rewrite.y,v 1.27.2.1 2002/06/20 13:41:20 gray Exp $";
 #endif
 
 typedef long RWSTYPE;
@@ -157,6 +157,7 @@ typedef enum {
         Attr,
         Attr_asgn,
         Attr_check,
+       Attr_delete,
         Max_mtxtype
 } Mtxtype;
 
@@ -426,6 +427,7 @@ typedef struct {
 typedef struct {
         COMMON_EXPR_MTX
         int       attrno;   /* Attribute number */
+       MTX       *index;   /* Index expression */
         MTX       *rval;    /* Rvalue */
 } ATTR_MTX;
 
@@ -560,10 +562,10 @@ static MTX * mtx_cond(MTX *cond, MTX *if
 static MTX * mtx_coerce(Datatype type, MTX *arg);
 static MTX * mtx_call(FUNCTION *fun, MTX *args);
 static MTX * mtx_builtin(builtin_t *bin, MTX *args);
-static MTX * mtx_attr(DICT_ATTR *attr);
-static MTX * mtx_attr_asgn(DICT_ATTR *attr, MTX *rval);
-static MTX * mtx_attr_check(DICT_ATTR *attr);
-
+static MTX * mtx_attr(DICT_ATTR *attr, MTX *index);
+static MTX * mtx_attr_asgn(DICT_ATTR *attr, MTX *index, MTX *rval);
+static MTX * mtx_attr_check(DICT_ATTR *attr, MTX *index);
+static MTX * mtx_attr_delete(DICT_ATTR *attr, MTX *index);
 static MTX * coerce(MTX  *arg, Datatype type);
 /*
  * Regular expressions
@@ -625,7 +627,7 @@ static void run_init(pctr_t pc, VALUE_PA
 };
 
 %token <type>   TYPE
-%token IF ELSE RETURN WHILE FOR DO BREAK CONTINUE
+%token IF ELSE RETURN WHILE FOR DO BREAK CONTINUE DELETE
 %token <string> STRING IDENT
 %token <number> NUMBER REFERENCE
 %token <var> VARIABLE
@@ -952,6 +954,14 @@ stmt    : begin list end
                   $$->jump.link = (MTX*)loop_last->lp_cont;
                   loop_last->lp_cont = (JUMP_MTX*)$$;
           }
+        | DELETE ATTR ';'
+          {
+                 $$ = mtx_attr_delete($2, NULL);
+         }
+       | DELETE ATTR '(' expr ')' ';'
+          {
+                 $$ = mtx_attr_delete($2, $4);
+         }
         ;
 
 while   : WHILE
@@ -1016,15 +1026,27 @@ expr    : NUMBER
           }
         | ATTR
           {
-                  $$ = mtx_attr($1);
+                  $$ = mtx_attr($1, NULL);
           }
-        | '*' ATTR
+        | ATTR '(' expr ')'
           {
-                  $$ = mtx_attr_check($2);
+                  $$ = mtx_attr($1, $3);
           }
+        | '*' ATTR 
+          {
+                  $$ = mtx_attr_check($2, NULL);
+          }
+        | '*' ATTR '(' expr ')'
+          {
+                 $$ = mtx_attr_check($2, $4);
+         }
         | ATTR '=' expr
           {
-                  $$ = mtx_attr_asgn($1, $3);
+                  $$ = mtx_attr_asgn($1, NULL, $3);
+          }
+        | ATTR '(' expr ')' '=' expr
+          {
+                  $$ = mtx_attr_asgn($1, $3, $6);
           }
         | FUN '(' args ')'
           {
@@ -1454,6 +1476,7 @@ static struct keyword rw_kw[] = {
         "while",    WHILE,
         "break",    BREAK,
         "continue", CONTINUE,
+       "delete",   DELETE,
         NULL
 };
 
@@ -2228,30 +2251,35 @@ attr_datatype(type)
 }
 
 MTX *
-mtx_attr(attr)
+mtx_attr(attr, index)
         DICT_ATTR *attr;
+       MTX *index;
 {
         ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr);
         mtx_append(mtx);
         mtx->attrno   = attr->value;
         mtx->datatype = attr_datatype(attr->type);
+       mtx->index = index;
         return (MTX*)mtx;
 }
 
 MTX *
-mtx_attr_check(attr)
+mtx_attr_check(attr, index)
         DICT_ATTR *attr;
+       MTX *index;
 {
         ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_check);
         mtx_append(mtx);
         mtx->attrno   = attr->value;
         mtx->datatype = Integer;
+       mtx->index = index;
         return (MTX*)mtx;
 }
 
 MTX *
-mtx_attr_asgn(attr, rval)
+mtx_attr_asgn(attr, index, rval)
         DICT_ATTR *attr;
+       MTX       *index;
         MTX       *rval;
 {
         ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_asgn);
@@ -2266,11 +2294,25 @@ mtx_attr_asgn(attr, rval)
                        datatype_str(mtx->datatype));
                 rval = coerce(rval, mtx->datatype);
         }
+       mtx->index = index;
         mtx->rval = rval;
         return (MTX*)mtx;
 }
 
 MTX *
+mtx_attr_delete(attr, index)
+        DICT_ATTR *attr;
+       MTX *index;
+{
+        ATTR_MTX *mtx = (ATTR_MTX*)mtx_alloc(Attr_delete);
+        mtx_append(mtx);
+        mtx->attrno   = attr->value;
+        mtx->datatype = attr_datatype(attr->type);
+       mtx->index = index;
+        return (MTX*)mtx;
+}
+
+MTX *
 mtx_bin(opcode, arg1, arg2)
         Bopcode opcode;
         MTX     *arg1, *arg2;
@@ -2778,24 +2820,34 @@ debug_print_mtxlist(s)
                         break;
                 
                 CASE (Attr)
-                        fprintf(fp, "%3.3s A:%d",
+                        fprintf(fp, "%3.3s A:%d I:%d",
                                 datatype_str(mtx->gen.datatype),
-                                mtx->attr.attrno);
+                                mtx->attr.attrno,
+                               mtx->attr.index);
                         break;
 
                 CASE (Attr_check)
-                        fprintf(fp, "%3.3s A:%d",
+                        fprintf(fp, "%3.3s A:%d I:%d",
                                 datatype_str(mtx->gen.datatype),
-                                mtx->attr.attrno);
+                                mtx->attr.attrno,
+                               mtx->attr.index);
                         break;
                         
                 CASE (Attr_asgn)
-                        fprintf(fp, "%3.3s A:%d M:%d",
+                        fprintf(fp, "%3.3s A:%d I:%d M:%d",
                                 datatype_str(mtx->gen.datatype),
                                 mtx->attr.attrno,
+                               mtx->attr.index,
                                 LINK(mtx->attr.rval));
                         break;
-                        
+
+               CASE (Attr_delete)
+                       fprintf(fp, "%3.3s A:%d I:%d",
+                               datatype_str(mtx->gen.datatype),
+                               mtx->attr.attrno,
+                               mtx->attr.index);
+                       break;
+                               
                 default:
                         fprintf(fp, "UNKNOWN: %d", mtx->gen.type);
                 }
@@ -3082,8 +3134,8 @@ pass2()
                                         case String:
                                                 /*NO STRING OPS SO FAR */;
                                         }
-                                } else if (mtx->bin.opcode == And ||
-                                           mtx->bin.opcode == Or) {
+                                } else if (mtx->bin.opcode == And
+                                          || mtx->bin.opcode == Or) {
                                         mtx_bool(mtx);
                                 }
                                 break;
@@ -3091,6 +3143,16 @@ pass2()
                         case Jump:
                                 if (mtx->jump.dest == mtx->jump.next)
                                         mtx_remove(mtx);
+                               break;
+
+                       case Attr:
+                       case Attr_asgn:
+                       case Attr_check:
+                       case Attr_delete:
+                               /*FIXME: the rw_attr.0 functions should
+                                 expect an immediate value after the
+                                 attribute number */
+                               break;
                         }
                         mtx = next;
                 }
@@ -3235,9 +3297,15 @@ static void rw_popa();
 static void rw_call();
 static void rw_builtin();
 static void rw_attrs();
+static void rw_attrs0();
 static void rw_attrn();
+static void rw_attrn0();
 static void rw_attrcheck();
+static void rw_attrcheck0();
 static void rw_attrasgn();
+static void rw_attrasgn0();
+static void rw_attr_delete();
+static void rw_attr_delete0();
 
 INSTR bin_codetab[] = {
         rw_eq,              
@@ -3453,25 +3521,44 @@ codegen()
                 case Attr:
                         switch (mtx->attr.datatype) {
                         case Integer:
-                                code(rw_attrn);
+                               if (mtx->attr.index)
+                                       code(rw_attrn);
+                               else
+                                       code(rw_attrn0);
                                 break;
                         case String:
-                                code(rw_attrs);
+                               if (mtx->attr.index)
+                                       code(rw_attrs);
+                               else
+                                       code(rw_attrs0);
                                 break;
                         }
                         data(mtx->attr.attrno);
                         break;
 
                 case Attr_check:
-                        code(rw_attrcheck);
+                       if (mtx->attr.index) 
+                               code(rw_attrcheck);
+                       else
+                               code(rw_attrcheck0);
                         data(mtx->attr.attrno);
                         break;
                         
                 case Attr_asgn:
-                        code(rw_attrasgn);
+                       if (mtx->attr.index)
+                               code(rw_attrasgn);
+                       else
+                               code(rw_attrasgn0);
                         data(mtx->attr.attrno);
                         break;
-                                
+
+               case Attr_delete:
+                       if (mtx->attr.index)
+                               code(rw_attr_delete);
+                       else
+                               code(rw_attr_delete0);
+                       data(mtx->attr.attrno);
+                       break;
                 }
         }
 
@@ -3887,47 +3974,79 @@ rw_asgn()
  * Check if the A/V pair is supplied in the request
  */
 void
+rw_attrcheck0()
+{
+        int attr = (int) rw_rt.code[rw_rt.pc++];
+
+       pushn(avl_find(rw_rt.request, attr) != NULL);
+}
+
+void
 rw_attrcheck()
 {
         int attr = (int) rw_rt.code[rw_rt.pc++];
+       RWSTYPE index;
+       VALUE_PAIR *p = rw_rt.request;
 
-        pushn(avl_find(rw_rt.request, attr) != NULL);
+       cpopn(&index);
+       pushn(avl_find_n(rw_rt.request, attr, index) != NULL);
 }
 
 /*
  * Assign a value to an A/V pair
  */
 void
-rw_attrasgn()
+attrasgn_internal(attr, pair, val)
+       int attr;
+       VALUE_PAIR *pair;
+       RWSTYPE val;
 {
-        int attr = (int) rw_rt.code[rw_rt.pc++];
-        RWSTYPE val;
-        VALUE_PAIR *pair;
-        
-        cpopn(&val);
-        if ((pair = avl_find(rw_rt.request, attr)) == NULL) {
+       if (!pair) {
                 pair = avp_create(attr, 0, NULL, 0);
                 if (!pair)
                         rw_error("can't create A/V pair");
                 avl_add_pair(&rw_rt.request, pair);
         }
-        switch (pair->type) {
-        case TYPE_STRING:
-        case TYPE_DATE:
-                replace_string(&pair->strvalue, (char*)val);
-                pair->strlength = strlen((char*) val);
-                break;
-        case TYPE_INTEGER:
-        case TYPE_IPADDR:
-                pair->lvalue = val;
-                break;
-        }
+               
+       switch (pair->type) {
+       case TYPE_STRING:
+       case TYPE_DATE:
+               replace_string(&pair->strvalue, (char*)val);
+               pair->strlength = strlen((char*) val);
+               break;
+       case TYPE_INTEGER:
+       case TYPE_IPADDR:
+               pair->lvalue = val;
+               break;
+       }
+       
+       pushn(val);
+}
 
-        pushn(val);
+void
+rw_attrasgn0()
+{
+        int attr = (int) rw_rt.code[rw_rt.pc++];
+        RWSTYPE val;
+        
+        cpopn(&val);
+       attrasgn_internal(attr, avl_find(rw_rt.request, attr), val);
 }
 
 void
-rw_attrs()
+rw_attrasgn()
+{
+        int attr = (int) rw_rt.code[rw_rt.pc++];
+        RWSTYPE val;
+       RWSTYPE index;
+
+        cpopn(&val);
+       cpopn(&index);
+       attrasgn_internal(attr, avl_find_n(rw_rt.request, attr, index), val);
+}
+
+void
+rw_attrs0()
 {
         int attr = (int) rw_rt.code[rw_rt.pc++];
         VALUE_PAIR *pair;
@@ -3939,7 +4058,7 @@ rw_attrs()
 }
 
 void
-rw_attrn()
+rw_attrn0()
 {
         int attr = (int) rw_rt.code[rw_rt.pc++];
         VALUE_PAIR *pair;
@@ -3948,6 +4067,51 @@ rw_attrn()
                 pushn(0);
         else
                 pushn(pair->lvalue);
+}
+
+void
+rw_attrs()
+{
+        int attr = (int) rw_rt.code[rw_rt.pc++];
+        VALUE_PAIR *pair;
+       RWSTYPE index;
+
+       cpopn(&index);
+        if ((pair = avl_find_n(rw_rt.request, attr, index)) == NULL) 
+                pushs(&nil, 1);
+        else
+                pushstr(pair->strvalue, pair->strlength);
+}
+
+void
+rw_attrn()
+{
+        int attr = (int) rw_rt.code[rw_rt.pc++];
+        VALUE_PAIR *pair;
+       RWSTYPE index;
+
+       cpopn(&index);
+        if ((pair = avl_find_n(rw_rt.request, attr, index)) == NULL)
+                pushn(0);
+        else
+                pushn(pair->lvalue);
+}
+
+void
+rw_attr_delete0()
+{
+        int attr = (int) rw_rt.code[rw_rt.pc++];
+       avl_delete(&rw_rt.request, attr);
+}
+
+void
+rw_attr_delete()
+{
+        int attr = (int) rw_rt.code[rw_rt.pc++];
+       RWSTYPE index;
+
+       cpopn(&index);
+       avl_delete_n(&rw_rt.request, attr, index);
 }
 
 /*
Index: radlib/avl.c
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/radlib/avl.c 
/home/gray/radius-0.96-series/radlib/avl.c
--- /home/gray/tmp/gnu-radius-0.96.3/radlib/avl.c       Tue Mar 19 18:11:58 2002
+++ /home/gray/radius-0.96-series/radlib/avl.c  Thu Jun 20 16:42:22 2002
@@ -17,7 +17,7 @@
 
 #ifndef lint
 static char rcsid[] = 
-"$Id: avl.c,v 1.7.2.1 2002/03/19 16:11:58 gray Exp $";
+"$Id: avl.c,v 1.7.2.2 2002/06/20 13:42:22 gray Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -191,6 +191,19 @@ avl_find(first, attr)
        return first;
 }
 
+VALUE_PAIR * 
+avl_find_n(first, attr, n)
+       VALUE_PAIR *first; 
+       int attr;
+       int n;
+{
+       for ( ; first; first = first->next) {
+               if (first->attribute == attr && n-- == 0)
+                       break;
+       }
+       return first;
+}
+
 /* Delete the pairs with the matching attribute
  */
 void 
@@ -208,6 +221,29 @@ avl_delete(first, attr)
                        else
                                *first = next;
                        avp_free(pair);
+               } else
+                       last = pair;
+       }
+}
+
+/* Delete Nth matching pair */
+void 
+avl_delete_n(first, attr, n)
+       VALUE_PAIR **first; 
+       int attr;
+       int n;
+{
+       VALUE_PAIR *pair, *next, *last = NULL;
+
+       for (pair = *first; pair; pair = next) {
+               next = pair->next;
+               if (pair->attribute == attr && n-- == 0) {
+                       if (last)
+                               last->next = next;
+                       else
+                               *first = next;
+                       avp_free(pair);
+                       break;
                } else
                        last = pair;
        }
Index: test/raddb/users.in
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/test/raddb/users.in 
/home/gray/radius-0.96-series/test/raddb/users.in
--- /home/gray/tmp/gnu-radius-0.96.3/test/raddb/users.in        Tue Mar 19 
16:32:05 2002
+++ /home/gray/radius-0.96-series/test/raddb/users.in   Tue Jul  2 23:38:23 2002
@@ -42,7 +42,18 @@ crypt   Auth-Type = Crypt-Local,
 
 ## Access.exp: bad-one should be rejected.
 bad-one Auth-Type = Accept     NULL
-       
+
+## Expiration.exp
+expire  Auth-Type = Local,
+               Password = "expire",
+               Expiration = "Jan 01 1970"
+       Service-Type = Framed-User
+
+no-expire  Auth-Type = Local,
+               Password = "expire",
+               Expiration = "Jan 01 2011"
+       Service-Type = Framed-User
+
 ## Reply.exp: Test Reply Attributes
 reply   Auth-Type = Local,
                Password = "guessme"
Index: test/radiusd.m4
diff -rpu /home/gray/tmp/gnu-radius-0.96.3/test/radiusd.m4 
/home/gray/radius-0.96-series/test/radiusd.m4
--- /home/gray/tmp/gnu-radius-0.96.3/test/radiusd.m4    Tue Mar 19 16:32:05 2002
+++ /home/gray/radius-0.96-series/test/radiusd.m4       Tue Jul  2 23:56:15 2002
@@ -14,7 +14,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# $Id: radiusd.m4,v 1.3 2001/12/26 14:50:52 gray Exp $
+# $Id: radiusd.m4,v 1.3.2.1 2002/07/02 20:56:15 gray Exp $
 
 TOOLDIR(radiusd)
 BEGIN
@@ -113,6 +113,13 @@ SEQUENCE(Access,
 Checking Access Lists,
 [TEST(send auth 1 User-Name = QUOTE(bad-one),
  expect 3 Reply-Message = QUOTE([[Sorry, your account is currently 
closed]]ESC(\r,\n)))])
+
+SEQUENCE(Expiration,
+Checking Expiration Attribute,
+[TEST(send auth 1 User-Name = QUOTE(expire) Password = QUOTE(expire),
+ expect 3 Reply-Message = QUOTE([[Password Has Expired]]ESC(\r,\n)))
+ TEST(send auth 1 User-Name = QUOTE(no-expire) Password = QUOTE(expire),
+ expect 2)])
 
 IFSEQUENCE(Menu, USE_LIVINGSTON_MENUS,
 Checking Menus,


==============================================================================



reply via email to

[Prev in Thread] Current Thread [Next in Thread]