All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rlm_example.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 9893ce9add36d566546e1c0b1be509e02366167a $
19  * @file rlm_example.c
20  * @brief Example module code.
21  *
22  * @copyright 2013 The FreeRADIUS server project
23  * @copyright 2013 your name <your address>
24  */
25 RCSID("$Id: 9893ce9add36d566546e1c0b1be509e02366167a $")
26 
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/rad_assert.h>
30 
31 /*
32  * Define a structure for our module configuration.
33  *
34  * These variables do not need to be in a structure, but it's
35  * a lot cleaner to do so, and a pointer to the structure can
36  * be used as the instance handle.
37  */
38 typedef struct rlm_example_t {
39  bool boolean;
40  uint32_t value;
41  char const *string;
44 
45 /*
46  * A mapping of configuration file names to internal variables.
47  */
48 static const CONF_PARSER module_config[] = {
49  { FR_CONF_OFFSET("integer", PW_TYPE_INTEGER, rlm_example_t, value), .dflt = "1" },
50  { FR_CONF_OFFSET("boolean", PW_TYPE_BOOLEAN, rlm_example_t, boolean), .dflt = "no" },
51  { FR_CONF_OFFSET("string", PW_TYPE_STRING, rlm_example_t, string) },
52  { FR_CONF_OFFSET("ipaddr", PW_TYPE_IPV4_ADDR, rlm_example_t, ipaddr), .dflt = "*" },
54 };
55 
56 static int rlm_example_cmp(UNUSED void *instance, REQUEST *request, UNUSED VALUE_PAIR *thing, VALUE_PAIR *check,
57  UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
58 {
59  rad_assert(check->da->type == PW_TYPE_STRING);
60 
61  RINFO("Example-Paircmp called with \"%s\"", check->vp_strvalue);
62 
63  if (strcmp(check->vp_strvalue, "yes") == 0) return 0;
64  return 1;
65 }
66 
67 /*
68  * Do any per-module initialization that is separate to each
69  * configured instance of the module. e.g. set up connections
70  * to external databases, read configuration files, set up
71  * dictionary entries, etc.
72  */
73 static int mod_instantiate(CONF_SECTION *conf, void *instance)
74 {
75  rlm_example_t *inst = instance;
76 
77  /*
78  * Do more work here
79  */
80  if (!inst->boolean) {
81  cf_log_err_cs(conf, "Boolean is false: forcing error!");
82  return -1;
83  }
84 
85  paircompare_register_byname("Example-Paircmp", fr_dict_attr_by_num(NULL, 0, PW_USER_NAME), false,
86  rlm_example_cmp, inst);
87 
88  return 0;
89 }
90 
91 /*
92  * Find the named user in this modules database. Create the set
93  * of attribute-value pairs to check and reply with for this user
94  * from the database. The authentication code only needs to check
95  * the password, the rest is done here.
96  */
97 static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void *instance, REQUEST *request)
98 {
100 
101  /*
102  * Look for the 'state' attribute.
103  */
104  state = fr_pair_find_by_num(request->packet->vps, 0, PW_STATE, TAG_ANY);
105  if (state != NULL) {
106  RDEBUG("Found reply to access challenge");
107  return RLM_MODULE_OK;
108  }
109 
110  /*
111  * Create the challenge, and add it to the reply.
112  */
113  pair_make_reply("Reply-Message", "This is a challenge", T_OP_EQ);
114  pair_make_reply("State", "0", T_OP_EQ);
115 
116  /*
117  * Mark the packet as an Access-Challenge packet.
118  *
119  * The server will take care of sending it to the user.
120  */
121  request->reply->code = PW_CODE_ACCESS_CHALLENGE;
122  RDEBUG("Sending Access-Challenge");
123 
124  return RLM_MODULE_HANDLED;
125 }
126 
127 /*
128  * Authenticate the user with the given password.
129  */
130 static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(UNUSED void *instance, UNUSED REQUEST *request)
131 {
132  return RLM_MODULE_OK;
133 }
134 
135 #ifdef WITH_ACCOUNTING
136 /*
137  * Massage the request before recording it or proxying it
138  */
139 static rlm_rcode_t CC_HINT(nonnull) mod_preacct(UNUSED void *instance, UNUSED REQUEST *request)
140 {
141  return RLM_MODULE_OK;
142 }
143 
144 /*
145  * Write accounting information to this modules database.
146  */
147 static rlm_rcode_t CC_HINT(nonnull) mod_accounting(UNUSED void *instance, UNUSED REQUEST *request)
148 {
149  return RLM_MODULE_OK;
150 }
151 
152 /*
153  * See if a user is already logged in. Sets request->simul_count to the
154  * current session count for this user and sets request->simul_mpp to 2
155  * if it looks like a multilink attempt based on the requested IP
156  * address, otherwise leaves request->simul_mpp alone.
157  *
158  * Check twice. If on the first pass the user exceeds his
159  * max. number of logins, do a second pass and validate all
160  * logins by querying the terminal server (using eg. SNMP).
161  */
162 static rlm_rcode_t CC_HINT(nonnull) mod_checksimul(UNUSED void *instance, REQUEST *request)
163 {
164  request->simul_count=0;
165 
166  return RLM_MODULE_OK;
167 }
168 #endif
169 
170 
171 /*
172  * Only free memory we allocated. The strings allocated via
173  * cf_section_parse() do not need to be freed.
174  */
175 static int mod_detach(UNUSED void *instance)
176 {
177  /* free things here */
178  return 0;
179 }
180 
181 /*
182  * The module name should be the only globally exported symbol.
183  * That is, everything else should be 'static'.
184  *
185  * If the module needs to temporarily modify it's instantiation
186  * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
187  * The server will then take care of ensuring that the module
188  * is single-threaded.
189  */
190 extern module_t rlm_example;
191 module_t rlm_example = {
193  .name = "example",
194  .type = RLM_TYPE_THREAD_SAFE,
195  .inst_size = sizeof(rlm_example_t),
196  .config = module_config,
197  .instantiate = mod_instantiate,
198  .detach = mod_detach,
199  .methods = {
202 #ifdef WITH_ACCOUNTING
203  [MOD_PREACCT] = mod_preacct,
206 #endif
207  },
208 };
RFC2865 - Access-Challenge.
Definition: radius.h:102
static rlm_rcode_t mod_accounting(void *instance, REQUEST *request)
Write accounting data to Couchbase documents.
The module is OK, continue.
Definition: radiusd.h:91
Metadata exported by the module.
Definition: modules.h:134
struct rlm_example_t rlm_example_t
static const CONF_PARSER module_config[]
Definition: rlm_example.c:48
static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
Handle authorization requests using Couchbase document data.
#define RLM_TYPE_THREAD_SAFE
Module is threadsafe.
Definition: modules.h:75
#define UNUSED
Definition: libradius.h:134
#define RLM_MODULE_INIT
Definition: modules.h:86
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
static rlm_rcode_t CC_HINT(nonnull)
Definition: rlm_example.c:97
#define inst
Definition: token.h:46
static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request) CC_HINT(nonnull)
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
#define rad_assert(expr)
Definition: rad_assert.h:38
4 methods index for checksimul section.
Definition: modules.h:45
char const * string
Definition: rlm_example.c:41
3 methods index for accounting section.
Definition: modules.h:44
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
static rlm_rcode_t mod_checksimul(void *instance, REQUEST *request)
Check if a given user is already logged in.
static int mod_detach(UNUSED void *instance)
Definition: rlm_example.c:175
void void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt,...) CC_HINT(format(printf
0 methods index for authenticate section.
Definition: modules.h:41
A truth value.
Definition: radius.h:56
32 Bit unsigned integer.
Definition: radius.h:34
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
static rs_t * conf
Definition: radsniff.c:46
unsigned int state
Definition: proto_bfd.c:200
uint64_t magic
Used to validate module struct.
Definition: modules.h:135
static int mod_instantiate(CONF_SECTION *conf, void *instance)
Definition: rlm_example.c:73
#define TAG_ANY
Definition: pair.h:191
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
int paircompare_register_byname(char const *name, fr_dict_attr_t const *from, bool first_only, RAD_COMPARE_FUNC func, void *instance)
Register a function as compare function.
Definition: pair.c:351
#define pair_make_reply(_a, _b, _c)
Definition: radiusd.h:546
static int rlm_example_cmp(UNUSED void *instance, REQUEST *request, UNUSED VALUE_PAIR *thing, VALUE_PAIR *check, UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
Definition: rlm_example.c:56
fr_ipaddr_t ipaddr
Definition: rlm_example.c:42
2 methods index for preacct section.
Definition: modules.h:43
module_t rlm_example
Definition: rlm_example.c:191
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
Definition: pair.c:639
#define RINFO(fmt,...)
Definition: log.h:205
IPv4/6 prefix.
Definition: inet.h:41
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
Definition: pair.h:113
fr_dict_attr_t const * fr_dict_attr_by_num(fr_dict_t *dict, unsigned int vendor, unsigned int attr)
Lookup a fr_dict_attr_t by its vendor and attribute numbers.
Definition: dict.c:3519
String of printable characters.
Definition: radius.h:33
PW_TYPE type
Value type.
Definition: dict.h:80
1 methods index for authorize section.
Definition: modules.h:42
#define RCSID(id)
Definition: build.h:135
32 Bit IPv4 Address.
Definition: radius.h:35
The module handled the request, so stop.
Definition: radiusd.h:92
#define RDEBUG(fmt,...)
Definition: log.h:243
uint32_t value
Definition: rlm_example.c:40