6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2000 The FreeRADIUS server project
21 * FIXME add copyrights
30 #include "libradius.h"
34 static const char rcsid[] = "$Id$";
36 #define REALM_FORMAT_PREFIX 0
37 #define REALM_FORMAT_SUFFIX 1
39 typedef struct realm_config_t {
45 static realm_config_t config;
47 static CONF_PARSER module_config[] = {
48 { "format", PW_TYPE_STRING_PTR, &config.formatstring, "suffix" },
49 { "delimiter", PW_TYPE_STRING_PTR, &config.delim, "@" },
50 { NULL, -1, NULL, NULL } /* end the list */
54 * Internal function to cut down on duplicated code.
56 * Returns NULL on don't proxy, realm otherwise.
58 static REALM *check_for_realm(void *instance, REQUEST *request)
60 char namebuf[MAX_STRING_LEN];
62 char *realmname = (char *)NULL;
67 struct realm_config_t *inst = instance;
73 * If the request has a proxy entry, then it's a proxy
74 * reply, and we're walking through the module list again.
76 * In that case, don't bother trying to proxy the request
79 * Also, if there's no User-Name attribute, we can't
82 if ((request->proxy != NULL) ||
83 (request->username == NULL)) {
87 strncpy(namebuf, request->username->strvalue, MAX_STRING_LEN-1);
92 case REALM_FORMAT_SUFFIX:
94 /* DEBUG2(" rlm_realm: Checking for suffix after \"%c\"", inst->delim[0]); */
96 realmname = strchr(username, inst->delim[0]);
103 case REALM_FORMAT_PREFIX:
105 /* DEBUG2(" rlm_realm: Checking for prefix before \"%c\"", inst->delim[0]); */
107 ptr = strchr(username, inst->delim[0]);
111 realmname = username;
124 realm = realm_find(realmname);
129 /* make sure it's proxyable realm */
130 if (realm->notrealm) {
134 DEBUG2(" rlm_realm: Proxying request from user %s to realm %s",
135 username, realm->realm);
138 * If we've been told to strip the realm off, then do so.
140 if (realm->striprealm) {
142 * Create the Stripped-User-Name attribute, if it
146 vp = pairfind(request->packet->vps, PW_STRIPPED_USER_NAME);
148 vp = paircreate(PW_STRIPPED_USER_NAME, PW_TYPE_STRING);
150 radlog(L_ERR|L_CONS, "no memory");
153 strcpy(vp->strvalue, username);
154 vp->length = strlen((char *)vp->strvalue);
155 pairadd(&request->packet->vps, vp);
156 request->username = vp;
161 * Don't add a 'Realm' attribute, proxy.c does
166 * Perhaps accounting proxying was turned off.
168 if ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
169 (realm->acct_port == 0)) {
170 /* log a warning that the packet isn't getting proxied ??? */
171 DEBUG2("rlm_realm: acct_port is not set. proxy cancelled");
176 * Perhaps authentication proxying was turned off.
178 if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
179 (realm->auth_port == 0)) {
180 /* log a warning that the packet isn't getting proxied ??? */
181 DEBUG2("rlm_realm: auth_port is not set. proxy cancelled");
190 * Maybe add a "Proxy-To-Realm" attribute to the request.
192 * If it's a LOCAL realm, then don't bother.
194 static void add_proxy_to_realm(VALUE_PAIR **vps, REALM *realm)
199 * If it's the LOCAL realm, we do NOT proxy it, but
200 * we DO strip the User-Name, if told to do so.
202 if (strcmp(realm->server, "LOCAL") == 0) {
207 * Tell the server to proxy this request to another
210 vp = pairmake("Proxy-To-Realm", realm->realm, T_OP_EQ);
212 radlog(L_ERR|L_CONS, "no memory");
217 * Add it, even if it's already present.
223 * Perform the realm module instantiation. Configuration info is
224 * stored in *instance for later use.
227 static int realm_instantiate(CONF_SECTION *conf, void **instance)
229 struct realm_config_t *inst;
231 /* setup a storage area for instance data */
232 inst = rad_malloc(sizeof(struct realm_config_t));
234 if(cf_section_parse(conf, module_config) < 0) {
239 /* copy the configuration info into the instance data */
241 if(strcasecmp(config.formatstring, "suffix") == 0) {
242 inst->format = REALM_FORMAT_SUFFIX;
243 } else if(strcasecmp(config.formatstring, "prefix") == 0) {
244 inst->format = REALM_FORMAT_PREFIX;
246 radlog(L_ERR, "Bad value \"%s\" for realm format value", config.formatstring);
250 if(strlen(config.delim) != 1) {
251 radlog(L_ERR, "Bad value \"%s\" for realm delimiter value", config.delim);
255 inst->delim = config.delim;
257 /* set these to NULL to prevent other instances from reusing the data */
271 * Examine a request for a username with an realm, and if it
272 * corresponds to something in the realms file, set that realm as
275 * This should very nearly duplicate the old proxy_send() code
277 static int realm_authorize(void *instance, REQUEST *request)
282 * Check if we've got to proxy the request.
283 * If not, return without adding a Proxy-To-Realm
286 realm = check_for_realm(instance, request);
288 return RLM_MODULE_OK;
292 * Maybe add a Proxy-To-Realm attribute to the request.
294 add_proxy_to_realm(&request->config_items, realm);
296 return RLM_MODULE_UPDATED; /* try the next module */
300 * This does the exact same thing as the realm_authorize, it's just called
303 static int realm_preacct(void *instance, REQUEST *request)
305 const char *name = (char *)request->username->strvalue;
309 return RLM_MODULE_OK;
313 * Check if we've got to proxy the request.
314 * If not, return without adding a Proxy-To-Realm
317 realm = check_for_realm(instance, request);
319 return RLM_MODULE_OK;
324 * Maybe add a Proxy-To-Realm attribute to the request.
326 add_proxy_to_realm(&request->config_items, realm);
328 return RLM_MODULE_OK; /* try the next module */
331 static int realm_detach(void *instance)
333 struct realm_config_t *inst = instance;
339 static int realm_destroy(void)
341 /* We reuse this buffer across multiple instances, instead of
342 * freeing it in instantiate() after converting it to an int.
343 * That makes it a module-global variable, so it must be freed
345 free(config.formatstring);
349 /* globally exported name */
350 module_t rlm_realm = {
352 0, /* type: reserved */
353 NULL, /* initialization */
354 realm_instantiate, /* instantiation */
355 realm_authorize, /* authorization */
356 NULL, /* authentication */
357 realm_preacct, /* preaccounting */
358 NULL, /* accounting */
359 NULL, /* checksimul */
360 realm_detach, /* detach */
361 realm_destroy, /* destroy */