X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Frlm_attr_rewrite%2Frlm_attr_rewrite.c;h=fd477024f091d2a83a2d513857f22868688ac47a;hb=9960563934a7da222528a1d82224aecc207c8aa8;hp=7b982d8ebb237b16554b39dd72b5c131fb77fcfd;hpb=19dce8b3b729d8307676061b971b7eac997441f1;p=freeradius.git diff --git a/src/modules/rlm_attr_rewrite/rlm_attr_rewrite.c b/src/modules/rlm_attr_rewrite/rlm_attr_rewrite.c index 7b982d8..fd47702 100644 --- a/src/modules/rlm_attr_rewrite/rlm_attr_rewrite.c +++ b/src/modules/rlm_attr_rewrite/rlm_attr_rewrite.c @@ -15,42 +15,34 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * - * Copyright 2002 The FreeRADIUS server project + * Copyright 2002,2006 The FreeRADIUS server project * Copyright 2002 Kostas Kalevras */ -#include "config.h" -#include "autoconf.h" -#include "libradius.h" +#include +RCSID("$Id$") + +#include +#include -#include -#include -#include -#include "config.h" #ifdef HAVE_REGEX_H # include #endif -#include "radiusd.h" -#include "modules.h" -#include "conffile.h" - #define RLM_REGEX_INPACKET 0 #define RLM_REGEX_INCONFIG 1 #define RLM_REGEX_INREPLY 2 #define RLM_REGEX_INPROXY 3 #define RLM_REGEX_INPROXYREPLY 4 -static const char rcsid[] = "$Id$"; - typedef struct rlm_attr_rewrite_t { char *attribute; /* The attribute to search for */ - int attr_num; /* The attribute number */ + DICT_ATTR *da; /* The attribute definition */ char *search; /* The pattern to search for */ int search_len; /* The length of the search pattern */ - char *searchin_str; /* The VALUE_PAIR list to search in. Can be either packet,reply,proxy,proxy_reply or config */ + char *searchin_str; /* The VALUE_PAIR list to search in. Can be either packet,reply,proxy,proxy_reply or control (plus it's alias 'config') */ char searchin; /* The same as above just coded as a number for speed */ char *replace; /* The replacement */ int replace_len; /* The length of the replacement string */ @@ -58,11 +50,10 @@ typedef struct rlm_attr_rewrite_t { int nocase; /* Ignore case */ int new_attr; /* Boolean. Do we create a new attribute or not? */ int num_matches; /* Maximum number of matches */ - char *name; /* The module name */ + const char *name; /* The module name */ } rlm_attr_rewrite_t; - -static CONF_PARSER module_config[] = { +static const CONF_PARSER module_config[] = { { "attribute", PW_TYPE_STRING_PTR, offsetof(rlm_attr_rewrite_t,attribute), NULL, NULL }, { "searchfor", PW_TYPE_STRING_PTR, offsetof(rlm_attr_rewrite_t,search), NULL, NULL }, { "searchin", PW_TYPE_STRING_PTR, offsetof(rlm_attr_rewrite_t,searchin_str), NULL, "packet" }, @@ -74,12 +65,10 @@ static CONF_PARSER module_config[] = { { NULL, -1, 0, NULL, NULL } }; - static int attr_rewrite_instantiate(CONF_SECTION *conf, void **instance) { rlm_attr_rewrite_t *data; DICT_ATTR *dattr; - char *instance_name = NULL; /* * Set up a storage area for instance data @@ -131,17 +120,20 @@ static int attr_rewrite_instantiate(CONF_SECTION *conf, void **instance) data->searchin = RLM_REGEX_INPACKET; else if (strcmp(data->searchin_str, "config") == 0) data->searchin = RLM_REGEX_INCONFIG; + else if (strcmp(data->searchin_str, "control") == 0) + data->searchin = RLM_REGEX_INCONFIG; else if (strcmp(data->searchin_str, "reply") == 0) data->searchin = RLM_REGEX_INREPLY; +#ifdef WITH_PROXY else if (strcmp(data->searchin_str, "proxy") == 0) data->searchin = RLM_REGEX_INPROXY; else if (strcmp(data->searchin_str, "proxy_reply") == 0) data->searchin = RLM_REGEX_INPROXYREPLY; +#endif else { radlog(L_ERR, "rlm_attr_rewrite: Illegal searchin directive given. Assuming packet."); data->searchin = RLM_REGEX_INPACKET; } - free((char *)data->searchin_str); } dattr = dict_attrbyname(data->attribute); if (dattr == NULL) { @@ -149,13 +141,9 @@ static int attr_rewrite_instantiate(CONF_SECTION *conf, void **instance) data->attribute); return -1; } - data->attr_num = dattr->attr; + data->da = dattr; /* Add the module instance name */ - data->name = NULL; - instance_name = cf_section_name2(conf); - if (instance_name != NULL) - data->name = strdup(instance_name); - + data->name = cf_section_name2(conf); /* may be NULL */ *instance = data; @@ -176,24 +164,73 @@ static int do_attr_rewrite(void *instance, REQUEST *request) unsigned int len = 0; char err_msg[MAX_STRING_LEN]; unsigned int i = 0; + unsigned int j = 0; unsigned int counter = 0; char new_str[MAX_STRING_LEN]; char *ptr, *ptr2; char search_STR[MAX_STRING_LEN]; char replace_STR[MAX_STRING_LEN]; - int replace_len = 0; - if ((attr_vp = pairfind(request->config_items, PW_REWRITE_RULE)) != NULL){ - if (data->name == NULL || strcmp(data->name,attr_vp->strvalue)) + if ((attr_vp = pairfind(request->config_items, PW_REWRITE_RULE, 0)) != NULL){ + if (data->name == NULL || strcmp(data->name,attr_vp->vp_strvalue)) return RLM_MODULE_NOOP; } - if (!data->new_attr){ + if (data->new_attr){ + /* new_attribute = yes */ + if (!radius_xlat(replace_STR, sizeof(replace_STR), data->replace, request, NULL)) { + DEBUG2("%s: xlat on replace string failed.", data->name); + return ret; + } + attr_vp = pairmake(data->attribute,replace_STR,0); + if (attr_vp == NULL){ + DEBUG2("%s: Could not add new attribute %s with value '%s'", data->name, + data->attribute,replace_STR); + return ret; + } + switch(data->searchin){ + case RLM_REGEX_INPACKET: + pairadd(&request->packet->vps,attr_vp); + break; + case RLM_REGEX_INCONFIG: + pairadd(&request->config_items,attr_vp); + break; + case RLM_REGEX_INREPLY: + pairadd(&request->reply->vps,attr_vp); + break; +#ifdef WITH_PROXY + case RLM_REGEX_INPROXY: + if (!request->proxy) { + pairbasicfree(attr_vp); + return RLM_MODULE_NOOP; + } + pairadd(&request->proxy->vps, attr_vp); + break; + case RLM_REGEX_INPROXYREPLY: + if (!request->proxy_reply) { + pairbasicfree(attr_vp); + return RLM_MODULE_NOOP; + } + pairadd(&request->proxy_reply->vps, attr_vp); + break; +#endif + default: + radlog(L_ERR, "%s: Illegal value for searchin. Changing to packet.", data->name); + data->searchin = RLM_REGEX_INPACKET; + pairadd(&request->packet->vps,attr_vp); + break; + } + DEBUG2("%s: Added attribute %s with value '%s'", data->name,data->attribute,replace_STR); + ret = RLM_MODULE_OK; + } else { + int replace_len = 0; + + /* new_attribute = no */ switch (data->searchin) { case RLM_REGEX_INPACKET: - if (data->attr_num == PW_USER_NAME) + if (!data->da->vendor && (data->da->attr == PW_USER_NAME)) attr_vp = request->username; - else if (data->attr_num == PW_PASSWORD) + else if (!data->da->vendor && (data->da->attr == PW_USER_PASSWORD)) attr_vp = request->password; else tmp = request->packet->vps; @@ -204,6 +241,7 @@ static int do_attr_rewrite(void *instance, REQUEST *request) case RLM_REGEX_INREPLY: tmp = request->reply->vps; break; +#ifdef WITH_PROXY case RLM_REGEX_INPROXYREPLY: if (!request->proxy_reply) return RLM_MODULE_NOOP; @@ -214,21 +252,22 @@ static int do_attr_rewrite(void *instance, REQUEST *request) return RLM_MODULE_NOOP; tmp = request->proxy->vps; break; +#endif default: - radlog(L_ERR, "rlm_attr_rewrite: Illegal value for searchin. Changing to packet."); + radlog(L_ERR, "%s: Illegal value for searchin. Changing to packet.", data->name); data->searchin = RLM_REGEX_INPACKET; - attr_vp = pairfind(request->packet->vps, data->attr_num); + attr_vp = pairfind(request->packet->vps, data->da->attr, data->da->vendor); break; } do_again: if (tmp != NULL) - attr_vp = pairfind(tmp, data->attr_num); + attr_vp = pairfind(tmp, data->da->attr, data->da->vendor); if (attr_vp == NULL) { - DEBUG2("rlm_attr_rewrite: Could not find value pair for attribute %s",data->attribute); + DEBUG2("%s: Could not find value pair for attribute %s", data->name,data->attribute); return ret; } - if (attr_vp->strvalue == NULL || attr_vp->length == 0){ - DEBUG2("rlm_attr_rewrite: Attribute %s string value NULL or of zero length",data->attribute); + if (attr_vp->vp_strvalue == NULL || attr_vp->length == 0){ + DEBUG2("%s: Attribute %s string value NULL or of zero length", data->name,data->attribute); return ret; } cflags |= REG_EXTENDED; @@ -236,36 +275,33 @@ do_again: cflags |= REG_ICASE; if (!radius_xlat(search_STR, sizeof(search_STR), data->search, request, NULL) && data->search_len != 0) { - DEBUG2("rlm_attr_rewrite: xlat on search string failed."); - return ret; - } - } - if (data->new_attr){ - if (!radius_xlat(replace_STR, sizeof(replace_STR), data->replace, request, NULL)) { - DEBUG2("rlm_attr_rewrite: xlat on replace string failed."); + DEBUG2("%s: xlat on search string failed.", data->name); return ret; } - replace_len = strlen(replace_STR); - } - - if (!data->new_attr){ - unsigned int j = 0; if ((err = regcomp(&preg,search_STR,cflags))) { regerror(err, &preg, err_msg, MAX_STRING_LEN); - DEBUG2("rlm_attr_rewrite: regcomp() returned error: %s",err_msg); + DEBUG2("%s: regcomp() returned error: %s", data->name,err_msg); return ret; } + + if ((attr_vp->type == PW_TYPE_IPADDR) && + (attr_vp->vp_strvalue[0] == '\0')) { + inet_ntop(AF_INET, &(attr_vp->vp_ipaddr), + attr_vp->vp_strvalue, + sizeof(attr_vp->vp_strvalue)); + } + ptr = new_str; - ptr2 = attr_vp->strvalue; + ptr2 = attr_vp->vp_strvalue; counter = 0; for ( i = 0 ;i < (unsigned)data->num_matches; i++) { - err = regexec(&preg, ptr2, 9, pmatch, 0); + err = regexec(&preg, ptr2, REQUEST_MAX_REGEX, pmatch, 0); if (err == REG_NOMATCH) { if (i == 0) { - DEBUG2("rlm_attr_rewrite: No match found for attribute %s with value '%s'", - data->attribute, attr_vp->strvalue); + DEBUG2("%s: Does not match: %s = %s", data->name, + data->attribute, attr_vp->vp_strvalue); regfree(&preg); goto to_do_again; } else @@ -273,8 +309,8 @@ do_again: } if (err != 0) { regfree(&preg); - radlog(L_ERR, "rlm_attr_rewrite: match failure for attribute %s with value '%s'", - data->attribute, attr_vp->strvalue); + radlog(L_ERR, "%s: match failure for attribute %s with value '%s'", data->name, + data->attribute, attr_vp->vp_strvalue); return ret; } if (pmatch[0].rm_so == -1) @@ -286,27 +322,28 @@ do_again: counter += len; if (counter >= MAX_STRING_LEN) { regfree(&preg); - DEBUG2("rlm_attr_rewrite: Replacement out of limits for attribute %s with value '%s'", - data->attribute, attr_vp->strvalue); + DEBUG2("%s: Replacement out of limits for attribute %s with value '%s'", data->name, + data->attribute, attr_vp->vp_strvalue); return ret; } - strncpy(ptr, ptr2,len); + memcpy(ptr, ptr2,len); ptr += len; + *ptr = '\0'; ptr2 += pmatch[0].rm_eo; if (i == 0){ /* * We only run on the first match, sorry */ - for(j = 0; j <= 8; j++){ + for(j = 0; j <= REQUEST_MAX_REGEX; j++){ char *p; - char buffer[sizeof(attr_vp->strvalue)]; + char buffer[sizeof(attr_vp->vp_strvalue)]; /* - * Stolen from src/main/valuepair.c, paircmp() + * Stolen from src/main/valuepair.c, paircompare() */ - + /* * Delete old matches if the corresponding match does not * exist in the current regex @@ -320,8 +357,9 @@ do_again: break; } memcpy(buffer, - attr_vp->strvalue + pmatch[j].rm_so,pmatch[j].rm_eo); - buffer[pmatch[j].rm_eo] = '\0'; + attr_vp->vp_strvalue + pmatch[j].rm_so, + pmatch[j].rm_eo - pmatch[j].rm_so); + buffer[pmatch[j].rm_eo - pmatch[j].rm_so] = '\0'; p = strdup(buffer); request_data_add(request,request,REQUEST_DATA_REGEX | j,p,free); } @@ -330,7 +368,7 @@ do_again: if (!done_xlat){ if (data->replace_len != 0 && radius_xlat(replace_STR, sizeof(replace_STR), data->replace, request, NULL) == 0) { - DEBUG2("rlm_attr_rewrite: xlat on replace string failed."); + DEBUG2("%s: xlat on replace string failed.", data->name); return ret; } replace_len = (data->replace_len != 0) ? strlen(replace_STR) : 0; @@ -340,29 +378,33 @@ do_again: counter += replace_len; if (counter >= MAX_STRING_LEN) { regfree(&preg); - DEBUG2("rlm_attr_rewrite: Replacement out of limits for attribute %s with value '%s'", - data->attribute, attr_vp->strvalue); + DEBUG2("%s: Replacement out of limits for attribute %s with value '%s'", data->name, + data->attribute, attr_vp->vp_strvalue); return ret; } if (replace_len){ - strncpy(ptr, replace_STR, replace_len); + memcpy(ptr, replace_STR, replace_len); ptr += replace_len; + *ptr = '\0'; } } regfree(&preg); len = strlen(ptr2) + 1; /* We add the ending NULL */ counter += len; if (counter >= MAX_STRING_LEN){ - DEBUG2("rlm_attr_rewrite: Replacement out of limits for attribute %s with value '%s'", - data->attribute, attr_vp->strvalue); + DEBUG2("%s: Replacement out of limits for attribute %s with value '%s'", data->name, + data->attribute, attr_vp->vp_strvalue); return ret; } - strncpy(ptr, ptr2, len); + memcpy(ptr, ptr2, len); + ptr[len] = '\0'; - DEBUG2("rlm_attr_rewrite: Changed value for attribute %s from '%s' to '%s'", - data->attribute, attr_vp->strvalue, new_str); - attr_vp->length = strlen(new_str); - strncpy(attr_vp->strvalue, new_str, (attr_vp->length + 1)); + DEBUG2("%s: Changed value for attribute %s from '%s' to '%s'", data->name, + data->attribute, attr_vp->vp_strvalue, new_str); + if (pairparsevalue(attr_vp, new_str) == NULL) { + DEBUG2("%s: Could not write value '%s' into attribute %s: %s", data->name, new_str, data->attribute, fr_strerror()); + return ret; + } to_do_again: ret = RLM_MODULE_OK; @@ -373,38 +415,10 @@ to_do_again: goto do_again; } } - else{ - attr_vp = pairmake(data->attribute,replace_STR,0); - if (attr_vp == NULL){ - DEBUG2("rlm_attr_rewrite: Could not add new attribute %s with value '%s'", - data->attribute,replace_STR); - return ret; - } - switch(data->searchin){ - case RLM_REGEX_INPACKET: - pairadd(&request->packet->vps,attr_vp); - break; - case RLM_REGEX_INCONFIG: - pairadd(&request->config_items,attr_vp); - break; - case RLM_REGEX_INREPLY: - pairadd(&request->reply->vps,attr_vp); - break; - default: - radlog(L_ERR, "rlm_attr_rewrite: Illegal value for searchin. Changing to packet."); - data->searchin = RLM_REGEX_INPACKET; - pairadd(&request->packet->vps,attr_vp); - break; - } - DEBUG2("rlm_attr_rewrite: Added attribute %s with value '%s'",data->attribute,replace_STR); - ret = RLM_MODULE_OK; - } - return ret; } - static int attr_rewrite_accounting(void *instance, REQUEST *request) { return do_attr_rewrite(instance, request); @@ -414,19 +428,23 @@ static int attr_rewrite_authorize(void *instance, REQUEST *request) { return do_attr_rewrite(instance, request); } + static int attr_rewrite_authenticate(void *instance, REQUEST *request) { return do_attr_rewrite(instance, request); } + static int attr_rewrite_preacct(void *instance, REQUEST *request) { return do_attr_rewrite(instance, request); } -static int attr_rewrite_ismul(void *instance, REQUEST *request) + +static int attr_rewrite_checksimul(void *instance, REQUEST *request) { return do_attr_rewrite(instance, request); } +#ifdef WITH_PROXY static int attr_rewrite_preproxy(void *instance, REQUEST *request) { return do_attr_rewrite(instance, request); @@ -436,6 +454,7 @@ static int attr_rewrite_postproxy(void *instance, REQUEST *request) { return do_attr_rewrite(instance, request); } +#endif static int attr_rewrite_postauth(void *instance, REQUEST *request) { @@ -444,17 +463,6 @@ static int attr_rewrite_postauth(void *instance, REQUEST *request) static int attr_rewrite_detach(void *instance) { - rlm_attr_rewrite_t *data = (rlm_attr_rewrite_t *) instance; - - if (data->attribute) - free(data->attribute); - if (data->search) - free(data->search); - if (data->replace) - free(data->replace); - if (data->name) - free(data->name); - free(instance); return 0; } @@ -469,20 +477,23 @@ static int attr_rewrite_detach(void *instance) * is single-threaded. */ module_t rlm_attr_rewrite = { + RLM_MODULE_INIT, "attr_rewrite", RLM_TYPE_THREAD_UNSAFE, /* type */ - NULL, /* initialization */ attr_rewrite_instantiate, /* instantiation */ + attr_rewrite_detach, /* detach */ { attr_rewrite_authenticate, /* authentication */ attr_rewrite_authorize, /* authorization */ attr_rewrite_preacct, /* preaccounting */ attr_rewrite_accounting, /* accounting */ - attr_rewrite_ismul, /* checksimul */ + attr_rewrite_checksimul, /* checksimul */ +#ifdef WITH_PROXY attr_rewrite_preproxy, /* pre-proxy */ attr_rewrite_postproxy, /* post-proxy */ +#else + NULL, NULL, +#endif attr_rewrite_postauth /* post-auth */ }, - attr_rewrite_detach, /* detach */ - NULL, /* destroy */ };