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