[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3 Guile

The name Guile stands for GNU's Ubiquitous Intelligent Language for Extensions. It provides a Scheme interpreter conforming to the R4RS language specification. This section describes use of Guile as an extension language for GNU Radius. It assumes that the reader is sufficiently familiar with the Scheme language. For information about the language, refer to (r4rs)Top section `Top' in Revised(4) Report on the Algorithmic Language Scheme. For more information about Guile, see (guile)Top section `Overview' in The Guile Reference Manual.

Scheme procedures can be called for processing both authentication and accounting requests. The invocation of a Scheme procedure for an authentication request is triggered by the Scheme-Procedure attribute; the invocation for an accounting request is triggered by the Scheme-Acct-Procedure attribute. The following sections address these issues in more detail.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3.1 Data Representation

A/V pair lists are the main object Scheme functions operate upon. Scheme is extremely convenient for representation of such objects. A Radius A/V pair is represented by a Scheme pair; e.g.,

 
        Session-Timeout = 10

is represented in Guile as

 
        (cons "Session-Timeout" 10)

The car of the pair can contain either the attribute dictionary name or the attribute number. Thus, the above pair may also be written in Scheme as

 
        (cons 27 10)

(because Session-Timeout corresponds to attribute number 27).

Lists of A/V pairs are represented by Scheme lists. For example, the Radius pair list

 
        User-Name = "jsmith",
                User-Password = "guessme",
                NAS-IP-Address = 10.10.10.1,
                NAS-Port-Id = 10

is written in Scheme as

 
        (list
          (cons "User-Name" "jsmith")
          (cons "User-Password" "guessme")
          (cons "NAS-IP-Address" "10.10.10.1")
          (cons "NAS-Port-Id" 10))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3.2 Authentication with Scheme

The Scheme procedure used for authentication must be declared as follows:

Function Template: auth-function request-list check-list reply-list

Its arguments are:

request-list

The list of A/V pairs from the incoming request

check-list

The list of A/V pairs from the LHS of the profile entry that matched the request

reply-list

The list of A/V pairs from the RHS of the profile entry that matched the request

The function return value determines whether the authentication will succeed. The function must return either a boolean value or a pair. The return of #t causes authentication to succeed. The return of #f causes it to fail.

For a function to add something to the reply A/V pairs, it should return a pair in the form

 
    (cons return-code list)

where return-code is a boolean value of the same meaning as described above. list is a list of A/V pairs to be added to the reply list. For example, the following function will always deny the authentication, returning an appropriate message to the user:

 
(define (decline-auth request-list check-list reply-list)
  (cons #f
        (list
         (cons "Reply-Message"
               "\r\nSorry, you are not
                allowed to log in\r\n"))))

As a more constructive example, let's consider a function that allows the authentication only if a user name is found in its internal database:

 
(define staff-data
  (list
   (list "scheme"
         (cons
          (list (cons "NAS-IP-Address" "127.0.0.1"))
          (list (cons "Framed-MTU" "8096")))
         (cons
          '()
          (list (cons "Framed-MTU" "256"))))))
  
(define (auth req check reply)
  (let* ((username (assoc "User-Name" req))
         (reqlist (assoc username req))
         (reply-list '()))
    (if username
        (let ((user-data (assoc (cdr username) staff-data)))
          (rad-log L_INFO (format #f "~A" user-data))
          (if user-data
              (call-with-current-continuation
               (lambda (xx)
                 (for-each
                  (lambda (pair)
                    (cond
                     ((avl-match? req (car pair))
                      (set! reply-list (avl-merge
                                        reply-list
                                        (cdr pair)))
                      (xx #t))))
                  (cdr user-data))
                 #f)))))
    (cons
     #t
     reply-list)))

To trigger the invocation of the Scheme authentication function, assign its name to the Scheme-Procedure attribute in the RHS of a corresponding ‘raddb/users’ profile. For example:

 
DEFAULT Auth-Type = SQL
        Scheme-Procedure = "auth"

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3.3 Accounting with Scheme

The Scheme accounting procedure must be declared as follows:

Function Template: acct-function-name request-list

Its argument is:

request-list

The list of A/V pairs from the incoming request

The function must return a boolean value. The accounting succeeds only if it has returned #t.

Here is an example of a Scheme accounting function. The function dumps the contents of the incoming request to a file:

 
(define radius-acct-file "/var/log/acct/radius")

(define (acct req)
  (call-with-output-file radius-acct-file
    (lambda (port)
      (for-each (lambda (pair)
                  (display (car pair) port)
                  (display "=" port)
                  (display (cdr pair) port)
                  (newline port))
                req)
      (newline port)))
  #t)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3.4 Radius-Specific Functions

Scheme Function: avl-delete av-list attr

Delete from av-list the pairs with attribute attr.

Scheme Function: avl-merge dst src

Merge src into dst.

Scheme Function: avl-match? target list

Return #t if all pairs from list are present in target.

Scheme Function: rad-dict-name->attr name

Return a dictionary entry for the given attribute name or #f if no such name was found in the dictionary.

A dictionary entry is a list in the form

Scheme List: dict-entry name-string attr-number type-number vendor

where the arguments are as follows:

name-string

The attribute name

value-number

The attribute number

type-number

The attribute type

vendor

The vendor PEC, if the attribute is a vendor-specific one, or #f otherwise.

Scheme Function: rad-dict-value->name attr value

Returns the dictionary name of the given value for an integer-type attribute attr, which can be either an attribute number or its dictionary name.

Scheme Function: rad-dict-name->value attr value

Convert a symbolic attribute value name into its integer representation.

Scheme Function: rad-dict-pec->vendor pec

Convert a PEC to the vendor name.

Scheme Function: rad-log-open prio

Open Radius logging to the severity level prio.

Scheme Function: rad-log-close

Close a Radius logging channel opened by a previous call to rad-log-open.

Scheme Function: rad-rewrite-execute-string string

Interpret string as an invocation of a function in Rewrite language and execute it.

Return value: return of the corresponding Rewrite call, translated to the Scheme data type.

Scheme Function: rad-rewrite-execute arglist

Execute a Rewrite language function. (car arglist) is interpreted as a name of the Rewrite function to execute, and (cdr arglist) as a list of arguments to be passed to it.

Return value: return of the corresponding Rewrite call, translated to the Scheme data type.

Scheme Function: rad-openlog ident option facility

Scheme interface to the system openlog() call.

Scheme Function: rad-syslog prio text

Scheme interface to the system syslog() call.

Scheme Function: rad-closelog

Scheme interface to the system closelog() call.

Scheme Function: rad-utmp-putent status delay list radutmp_file radwtmp_file

Write the supplied data into the radutmp file. If radwtmp_file is not nil, the constructed entry is also appended to wtmp_file.

list is:

Scheme List: utmp-entry user-name orig-name port-id port-type session-id caller-id framed-ip nas-ip proto
user-name

The user name

orig-name

The original user name from the request

port-id

The value of the NAS-Port-Id attribute

port-type

A number or character indicating the port type

session-id

The session ID

caller-id

The value of the Calling-Station-Id attribute from the request

framed-ip

The framed IP assigned to the user

nas-ip

The NAS IP

proto

A number or character indicating the type of the connection


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Sergey Poznyakoff on December, 6 2008 using texi2html 1.78.