More docs & updates
[freeradius.git] / doc / module_interface
1
2 RLM Module Interface (for developers)
3 -------------------------------------
4
5 Section 1 - overview
6
7 Section 1.1 Intent of the modules.
8
9 The intent of modules is that they do small, simple, well-defined
10 things when RADIUS packets are received.  If the module does things
11 when RADIUS packets are NOT received, then it has no business being in
12 the server.  Similarly, the module infrastructure is NOT intended to
13 allow servers, applications, timed events, or anything other than
14 handling incoming RADIUS packets.
15
16 Allowing modules to do many things means that the server becomes
17 more unreliable, more difficult to maintain, and much more likely to
18 be vulnerable to security problems.
19
20 So the modules do something when RADIUS packets are received.  Modules
21 which do more (creating threads, forking programs) will NOT be added
22 to the server, and the server core will NOT be modified to enable
23 these kinds of modules.  Those functions more properly belong in a
24 seperate application.
25
26 Section 1.2 Module outline
27
28 The fundamental concepts of the rlm interface are module, instance, and
29 component.
30
31 A module is a chunk of code that knows how to deal with a particular kind of
32 database, or perhaps a collection of similar databases. Examples:
33
34   - rlm_sql contains code for talking to MySQL or Postgres, and for mapping
35     RADIUS records onto SQL tables.
36   - rlm_unix contains code for making radiusd fit in well on unix-like
37     systems, including getpw* authentication and utmp/wtmp-style logging.
38
39 An instance specifies the actual location of a collection data that can be
40 used by a module. Examples:
41
42   - /var/log/radutmp
43   - "the MySQL database on bigserver.theisp.com.example"
44
45 A module can have up to 4 (soon to be 5? 6?) components which act on RADIUS
46 requests at different stages. The components are:
47
48   - authorization: check that a user exists, decide on an authentication
49     method or proxy realm, and possibly apply some attributes to be returned
50     in the reply packet.
51   - authentication: verify that the password is correct.
52   - preaccounting: decide whether to proxy the request, and possibly add
53     attributes that should be included in any logs
54   - accounting: record the request in the log
55   - checksimul: count the number of active sessions for the user
56   - postauth: process the response before it's sent to the NAS
57   - preproxy: process a request before it's proxied
58   - postproxy: filter attributes from a reply to a
59     proxied request
60
61 A module declares which components it supports by putting function pointers
62 in its "module_t rlm_*" structure.
63
64 Section 2 - Module configuration:
65
66 The administrator requests the creation of a module instance by adding it
67 inside the modules{} block in radiusd.conf. The instance definition looks
68 like this:
69
70   module_name [instance_name] {
71     param1 = value1
72     param2 = value2
73     param3 = value3
74     ...
75   }
76
77 The module_name is used to load the module. To see the names of the available
78 modules, look for the rlm_*.so files in $installprefix/lib. The module_name
79 is that, minus the rlm_ and the .so.
80
81 instance_name is an identifier for distinguishing multiple instances of the
82 same module. If you are only loading a module once, you can leave out the
83 instance_name and it will be assumed to be the same as the module_name.
84
85 The parameters inside the module block are passed without interpretation to
86 the module and generally point to the exact location of a database or enable
87 optional features of the module. Each module should document what parameters
88 it accepts and what they do.
89
90 For each Access-Request that comes to the server, the authorize{}
91 block is called. Then one of the authtype{} blocks from authenticate{}
92 is called, depending on the Auth-Type attribute that was chosen by
93 authorize{}. Finally, the postauth{} block is called.  If authorize{}
94 set the Proxy-To-Realm attribute, then proxying takes over via
95 preproxy{} and postproxy{}, and the local authenticate{} phase is
96 skipped.
97
98 For each Accounting-Request that comes to the server, the preacct{} block is
99 called, followed by the accounting{} block. accounting{} is skipped if
100 preacct{} sets Proxy-To-Realm.
101
102 For an explanation of what "calling" a config block means, see
103 README.failover.
104
105 Section 3 - The lifetime of a module
106
107 When the server is starting up, or reinitializing itself as a result of a
108 SIGHUP, it reads the modules{} section. Each configured module will be loaded
109 and its init() method will be called.
110
111   int init(void)
112
113 The init() method should take care of
114 any setup that is not tied to a specific instance. It will only be called
115 once, even if there are multiple instances configured.
116
117 For each configured instance, after the init() method, the instantiate()
118 method is called. It is given a handle to the configuration block holding its
119 parameters, which it can access with cf_section_parse().
120
121   int instantiate(CONF_SECTION *cs, void **instance)
122
123 The instantiate() function should look up options in the config section, and
124 open whatever files or network connections are necessary for the module to do
125 its job. It also should create a structure holding all of the persistent
126 variables that are particular to this instance (open file descriptors,
127 configured pathnames, etc.) and store a pointer to it in *instance. That
128 void * becomes a handle (some would call it a "cookie") representing this
129 instance. The instance handle is passed as a parameter in all subsequent
130 calls to the module's methods, so they can determine which database they are
131 supposed to act on.
132
133 The authorize(), authenticate(), preaccounting(), and accounting() functions
134 are all called the same way:
135
136   int authorize(void *instance, REQUEST *request)
137   int authenticate(void *instance, REQUEST *request)
138   int preaccounting(void *instance, REQUEST *request)
139   int accounting(void *instance, REQUEST *request)
140
141 they each receive the instance handle and the request, and are expected to
142 act on the request using the database pointed to by the instance handle
143 (which was set by the instantiate() function).
144
145 When the server is being shut down (as the first part of SIGHUP for example)
146 detach() is called for each module instance.
147
148   int detach(void *instance)
149
150 The detach() method should release whatever resources were allocated by the
151 instantiate() method.
152
153 After all instances are detached, the destroy() method is called.
154
155   int destroy(void)
156
157 It should release resources that were acquired by the init() method.
158
159 --Alan Curry <pacman@world.std.com>