All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rlm_sometimes.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: e861b3f573f96a2447b217569aa2e16f8b927fed $
19  * @file rlm_sometimes.c
20  * @brief Switches between retuning different return codes.
21  *
22  * @copyright 2012 The FreeRADIUS server project
23  */
24 RCSID("$Id: e861b3f573f96a2447b217569aa2e16f8b927fed $")
25 
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/modules.h>
28 #include <freeradius-devel/rad_assert.h>
29 
30 /*
31  * The instance data for rlm_sometimes is the list of fake values we are
32  * going to return.
33  */
34 typedef struct rlm_sometimes_t {
35  char const *rcode_str;
37  uint32_t start;
38  uint32_t end;
41 
42 /*
43  * A mapping of configuration file names to internal variables.
44  *
45  * Note that the string is dynamically allocated, so it MUST
46  * be freed. When the configuration file parse re-reads the string,
47  * it free's the old one, and strdup's the new one, placing the pointer
48  * to the strdup'd string into 'config.string'. This gets around
49  * buffer over-flows.
50  */
51 static const CONF_PARSER module_config[] = {
52  { FR_CONF_OFFSET("rcode", PW_TYPE_STRING, rlm_sometimes_t, rcode_str), .dflt = "fail" },
53  { FR_CONF_OFFSET("key", PW_TYPE_TMPL | PW_TYPE_ATTRIBUTE, rlm_sometimes_t, key), .dflt = "&User-Name", .quote = T_BARE_WORD },
54  { FR_CONF_OFFSET("start", PW_TYPE_INTEGER, rlm_sometimes_t, start), .dflt = "0" },
55  { FR_CONF_OFFSET("end", PW_TYPE_INTEGER, rlm_sometimes_t, end), .dflt = "127" },
57 };
58 
59 static int mod_instantiate(CONF_SECTION *conf, void *instance)
60 {
61  rlm_sometimes_t *inst = instance;
62 
63  /*
64  * Convert the rcode string to an int, and get rid of it
65  */
67  if (inst->rcode == RLM_MODULE_UNKNOWN) {
68  cf_log_err_cs(conf, "Unknown module return code '%s'", inst->rcode_str);
69  return -1;
70  }
71 
72  return 0;
73 }
74 
75 /*
76  * A lie! It always returns!
77  */
78 static rlm_rcode_t sometimes_return(void *instance, REQUEST *request, RADIUS_PACKET *packet, RADIUS_PACKET *reply)
79 {
80  uint32_t hash;
81  uint32_t value;
82  rlm_sometimes_t *inst = instance;
83  VALUE_PAIR *vp;
84 
85  /*
86  * Set it to NOOP and the module will always do nothing
87  */
88  if (inst->rcode == RLM_MODULE_NOOP) return inst->rcode;
89 
90  /*
91  * Hash based on the given key. Usually User-Name.
92  */
93  tmpl_find_vp(&vp, request, inst->key);
94  if (!vp) return RLM_MODULE_NOOP;
95 
96  hash = fr_hash(&vp->data, vp->vp_length);
97  hash &= 0xff; /* ensure it's 0..255 */
98  value = hash;
99 
100  /*
101  * Ranges are INCLUSIVE.
102  * [start,end] returns "rcode"
103  * Everything else returns "noop"
104  */
105  if (value < inst->start) return RLM_MODULE_NOOP;
106  if (value > inst->end) return RLM_MODULE_NOOP;
107 
108  /*
109  * If we're returning "handled", then set the packet
110  * code in the reply, so that the server responds.
111  */
112  if ((inst->rcode == RLM_MODULE_HANDLED) && reply) {
113  switch (packet->code) {
115  reply->code = PW_CODE_ACCESS_ACCEPT;
116  break;
117 
120  break;
121 
122  case PW_CODE_COA_REQUEST:
123  reply->code = PW_CODE_COA_ACK;
124  break;
125 
127  reply->code = PW_CODE_DISCONNECT_ACK;
128  break;
129 
130  default:
131  break;
132  }
133  }
134 
135  return inst->rcode;
136 }
137 
138 static rlm_rcode_t CC_HINT(nonnull) mod_sometimes_packet(void *instance, REQUEST *request)
139 {
140  return sometimes_return(instance, request, request->packet, request->reply);
141 }
142 
143 static rlm_rcode_t CC_HINT(nonnull) mod_sometimes_reply(void *instance, REQUEST *request)
144 {
145  return sometimes_return(instance, request, request->reply, NULL);
146 }
147 
148 #ifdef WITH_PROXY
149 static rlm_rcode_t CC_HINT(nonnull) mod_pre_proxy(void *instance, REQUEST *request)
150 {
151  if (!request->proxy) return RLM_MODULE_NOOP;
152 
153  return sometimes_return(instance, request, request->proxy, request->proxy_reply);
154 }
155 
156 static rlm_rcode_t CC_HINT(nonnull) mod_post_proxy(void *instance, REQUEST *request)
157 {
158  if (!request->proxy_reply) return RLM_MODULE_NOOP;
159 
160  return sometimes_return(instance, request, request->proxy_reply, NULL);
161 }
162 #endif
163 
164 extern module_t rlm_sometimes;
165 module_t rlm_sometimes = {
167  .name = "sometimes",
168  .type = RLM_TYPE_HUP_SAFE, /* needed for radmin */
169  .inst_size = sizeof(rlm_sometimes_t),
170  .config = module_config,
171  .instantiate = mod_instantiate,
172  .methods = {
173  [MOD_AUTHENTICATE] = mod_sometimes_packet,
174  [MOD_AUTHORIZE] = mod_sometimes_packet,
175  [MOD_PREACCT] = mod_sometimes_packet,
176  [MOD_ACCOUNTING] = mod_sometimes_packet,
177 #ifdef WITH_PROXY
178  [MOD_PRE_PROXY] = mod_pre_proxy,
179  [MOD_POST_PROXY] = mod_post_proxy,
180 #endif
181  [MOD_POST_AUTH] = mod_sometimes_reply,
182 #ifdef WITH_COA
183  [MOD_RECV_COA] = mod_sometimes_packet,
184  [MOD_SEND_COA] = mod_sometimes_reply,
185 #endif
186  },
187 };
5 methods index for preproxy section.
Definition: modules.h:46
Metadata exported by the module.
Definition: modules.h:134
uint32_t fr_hash(void const *, size_t)
Definition: hash.c:727
char const * rcode_str
Definition: rlm_sometimes.c:35
7 methods index for postauth section.
Definition: modules.h:48
#define RLM_MODULE_INIT
Definition: modules.h:86
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
Error resolving rcode (should not be returned by modules).
Definition: radiusd.h:99
#define inst
#define RLM_TYPE_HUP_SAFE
Will be restarted on HUP.
Definition: modules.h:79
RFC3575/RFC5176 - Disconnect-Ack (positive)
Definition: radius.h:106
static const CONF_PARSER module_config[]
Definition: rlm_sometimes.c:51
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
static rlm_rcode_t sometimes_return(void *instance, REQUEST *request, RADIUS_PACKET *packet, RADIUS_PACKET *reply)
Definition: rlm_sometimes.c:78
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:124
RFC2866 - Accounting-Response.
Definition: radius.h:96
const FR_NAME_NUMBER mod_rcode_table[]
Definition: modcall.c:186
RFC3575/RFC5176 - CoA-Ack (positive)
Definition: radius.h:109
RFC2865 - Access-Request.
Definition: radius.h:92
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
Definition: token.c:451
vp_tmpl_t * key
Definition: rlm_sometimes.c:39
int tmpl_find_vp(VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt)
Returns the first VP matching a vp_tmpl_t.
Definition: tmpl.c:2224
RFC2866 - Accounting-Request.
Definition: radius.h:95
static int mod_instantiate(CONF_SECTION *conf, void *instance)
Definition: rlm_sometimes.c:59
static rlm_rcode_t CC_HINT(nonnull)
unsigned int code
Packet code (type).
Definition: libradius.h:155
RFC2865 - Access-Accept.
Definition: radius.h:93
3 methods index for accounting section.
Definition: modules.h:44
module_t rlm_sometimes
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
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
32 Bit unsigned integer.
Definition: radius.h:34
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
RFC3575/RFC5176 - CoA-Request.
Definition: radius.h:108
static rs_t * conf
Definition: radsniff.c:46
Module succeeded without doing anything.
Definition: radiusd.h:96
uint64_t magic
Used to validate module struct.
Definition: modules.h:135
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
struct rlm_sometimes_t rlm_sometimes_t
6 methods index for postproxy section.
Definition: modules.h:47
2 methods index for preacct section.
Definition: modules.h:43
8 methods index for recvcoa section.
Definition: modules.h:50
#define PW_TYPE_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use PW_TYPE_TMPL).
Definition: conffile.h:201
9 methods index for sendcoa section.
Definition: modules.h:51
String of printable characters.
Definition: radius.h:33
rlm_rcode_t rcode
Definition: rlm_sometimes.c:36
#define PW_TYPE_TMPL
CONF_PAIR should be parsed as a template.
Definition: conffile.h:208
1 methods index for authorize section.
Definition: modules.h:42
#define RCSID(id)
Definition: build.h:135
The module handled the request, so stop.
Definition: radiusd.h:92
A source or sink of value data.
Definition: tmpl.h:187
RFC3575/RFC5176 - Disconnect-Request.
Definition: radius.h:105
value_data_t data
Definition: pair.h:133