import from HEAD:
[freeradius.git] / src / modules / rlm_always / rlm_always.c
1 /*
2  * rlm_always.c
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation; either version 2 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program; if not, write to the Free Software
16  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Copyright 2000  The FreeRADIUS server project
19  */
20
21 #include "autoconf.h"
22 #include "libradius.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "radiusd.h"
29 #include "modules.h"
30 #include "conffile.h"
31
32 static const char rcsid[] = "$Id$";
33
34 /*
35  *      The instance data for rlm_always is the list of fake values we are
36  *      going to return.
37  */
38 typedef struct rlm_always_t {
39         char    *rcode_str;
40         int     rcode;
41         int     simulcount;
42         int     mpp;
43 } rlm_always_t;
44
45 /*
46  *      A mapping of configuration file names to internal variables.
47  *
48  *      Note that the string is dynamically allocated, so it MUST
49  *      be freed.  When the configuration file parse re-reads the string,
50  *      it free's the old one, and strdup's the new one, placing the pointer
51  *      to the strdup'd string into 'config.string'.  This gets around
52  *      buffer over-flows.
53  */
54 static CONF_PARSER module_config[] = {
55   { "rcode",      PW_TYPE_STRING_PTR, offsetof(rlm_always_t,rcode_str),
56     NULL, "fail" },
57   { "simulcount", PW_TYPE_INTEGER,    offsetof(rlm_always_t,simulcount),
58     NULL, "0" },
59   { "mpp",        PW_TYPE_BOOLEAN,    offsetof(rlm_always_t,mpp),
60     NULL, "no" },
61
62   { NULL, -1, 0, NULL, NULL }           /* end the list */
63 };
64
65 static int str2rcode(const char *s)
66 {
67         if(!strcasecmp(s, "reject"))
68                 return RLM_MODULE_REJECT;
69         else if(!strcasecmp(s, "fail"))
70                 return RLM_MODULE_FAIL;
71         else if(!strcasecmp(s, "ok"))
72                 return RLM_MODULE_OK;
73         else if(!strcasecmp(s, "handled"))
74                 return RLM_MODULE_HANDLED;
75         else if(!strcasecmp(s, "invalid"))
76                 return RLM_MODULE_INVALID;
77         else if(!strcasecmp(s, "userlock"))
78                 return RLM_MODULE_USERLOCK;
79         else if(!strcasecmp(s, "notfound"))
80                 return RLM_MODULE_NOTFOUND;
81         else if(!strcasecmp(s, "noop"))
82                 return RLM_MODULE_NOOP;
83         else if(!strcasecmp(s, "updated"))
84                 return RLM_MODULE_UPDATED;
85         else {
86                 radlog(L_ERR|L_CONS,
87                         "rlm_always: Unknown module rcode '%s'.\n", s);
88                 return -1;
89         }
90 }
91
92 static int always_instantiate(CONF_SECTION *conf, void **instance)
93 {
94         rlm_always_t *data;
95
96         /*
97          *      Set up a storage area for instance data
98          */
99         data = rad_malloc(sizeof(*data));
100         if (!data) {
101                 return -1;
102         }
103         memset(data, 0, sizeof(*data));
104
105         /*
106          *      If the configuration parameters can't be parsed, then
107          *      fail.
108          */
109         if (cf_section_parse(conf, data, module_config) < 0) {
110                 free(data);
111                 return -1;
112         }
113
114         /*
115          *      Convert the rcode string to an int, and get rid of it
116          */
117         data->rcode = str2rcode(data->rcode_str);
118         free(data->rcode_str);
119         data->rcode_str = NULL;
120         if (data->rcode == -1) {
121                 free(data);
122                 return -1;
123         }
124
125         *instance = data;
126
127         return 0;
128 }
129
130 /*
131  *      Just return the rcode ... this function is autz, auth, acct, and
132  *      preacct!
133  */
134 static int always_return(void *instance, REQUEST *request)
135 {
136         /* quiet the compiler */
137         request = request;
138
139         return ((struct rlm_always_t *)instance)->rcode;
140 }
141
142 /*
143  *      checksimul fakes some other variables besides the rcode...
144  */
145 static int always_checksimul(void *instance, REQUEST *request)
146 {
147         struct rlm_always_t *inst = instance;
148
149         request->simul_count = inst->simulcount;
150
151         if (inst->mpp)
152                 request->simul_mpp = 2;
153
154         return inst->rcode;
155 }
156
157 static int always_detach(void *instance)
158 {
159         free(instance);
160         return 0;
161 }
162
163 module_t rlm_always = {
164         "always",
165         RLM_TYPE_THREAD_SAFE,           /* type */
166         NULL,                           /* initialization */
167         always_instantiate,             /* instantiation */
168         {
169                 always_return,          /* authentication */
170                 always_return,          /* authorization */
171                 always_return,          /* preaccounting */
172                 always_return,          /* accounting */
173                 always_checksimul,      /* checksimul */
174                 always_return,          /* pre-proxy */
175                 always_return,          /* post-proxy */
176                 always_return           /* post-auth */
177         },
178         always_detach,                  /* detach */
179         NULL,                           /* destroy */
180 };