X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Frlm_counter%2Frlm_counter.c;h=d5ed5d25791ec0c5076a24f05728c550d5ce6e5e;hb=9d6f24b3fe0128e63747be0f0b0ce58cb98504cf;hp=d52153588fb13afcd81258143fd7667d18f8455d;hpb=09dc94d48effb65dcdf62a2a8f49a088fac8f27f;p=freeradius.git diff --git a/src/modules/rlm_counter/rlm_counter.c b/src/modules/rlm_counter/rlm_counter.c index d521535..d5ed5d2 100644 --- a/src/modules/rlm_counter/rlm_counter.c +++ b/src/modules/rlm_counter/rlm_counter.c @@ -15,28 +15,24 @@ * * 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 2001 The FreeRADIUS server project + * Copyright 2001,2006 The FreeRADIUS server project * Copyright 2001 Alan DeKok * Copyright 2001-3 Kostas Kalevras */ -#include "config.h" -#include "autoconf.h" -#include "libradius.h" +#include +RCSID("$Id$") + +#include +#include -#include -#include -#include #include -#include "radiusd.h" -#include "modules.h" -#include "conffile.h" +#include "config.h" #include -#include #ifdef NEEDS_GDBM_SYNC # define GDBM_SYNCOPT GDBM_SYNC @@ -56,8 +52,6 @@ #define UNIQUEID_MAX_LEN 32 -static const char rcsid[] = "$Id$"; - /* * Define a structure for our module configuration. * @@ -70,16 +64,16 @@ typedef struct rlm_counter_t { char *reset; /* daily, weekly, monthly, never or user defined */ char *key_name; /* User-Name */ char *count_attribute; /* Acct-Session-Time */ - char *return_attribute; /* Session-Timeout */ char *counter_name; /* Daily-Session-Time */ char *check_name; /* Daily-Max-Session */ + char *reply_name; /* Session-Timeout */ char *service_type; /* Service-Type to search for */ int cache_size; int service_val; int key_attr; int count_attr; - int return_attr; int check_attr; + int reply_attr; time_t reset_time; /* The time of the next reset. */ time_t last_reset; /* The time of the last reset. */ int dict_attr; /* attribute number for the counter. */ @@ -114,14 +108,14 @@ typedef struct rad_counter { * to the strdup'd string into 'config.string'. This gets around * buffer over-flows. */ -static CONF_PARSER module_config[] = { +static const CONF_PARSER module_config[] = { { "filename", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,filename), NULL, NULL }, { "key", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,key_name), NULL, NULL }, { "reset", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,reset), NULL, NULL }, { "count-attribute", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,count_attribute), NULL, NULL }, - { "return-attribute", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,return_attribute), NULL, NULL }, { "counter-name", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,counter_name), NULL, NULL }, { "check-name", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,check_name), NULL, NULL }, + { "reply-name", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,reply_name), NULL, NULL }, { "allowed-servicetype", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,service_type),NULL, NULL }, { "cache-size", PW_TYPE_INTEGER, offsetof(rlm_counter_t,cache_size), NULL, "1000" }, { NULL, -1, 0, NULL, NULL } @@ -151,12 +145,12 @@ static int counter_cmp(void *instance, /* * Find the key attribute. */ - key_vp = pairfind(request, data->key_attr); + key_vp = pairfind(request, data->key_attr, 0); if (key_vp == NULL) { return RLM_MODULE_NOOP; } - key_datum.dptr = key_vp->strvalue; + key_datum.dptr = key_vp->vp_strvalue; key_datum.dsize = key_vp->length; count_datum = gdbm_fetch(data->gdbm, key_datum); @@ -167,7 +161,7 @@ static int counter_cmp(void *instance, memcpy(&counter, count_datum.dptr, sizeof(rad_counter)); free(count_datum.dptr); - return counter.user_counter - check->lvalue; + return counter.user_counter - check->vp_integer; } @@ -244,21 +238,21 @@ static int reset_db(rlm_counter_t *data) static int find_next_reset(rlm_counter_t *data, time_t timeval) { - int ret=0; - unsigned int num=1; - char last = 0; + int ret = 0; + size_t len; + unsigned int num = 1; + char last = '\0'; struct tm *tm, s_tm; char sCurrentTime[40], sNextTime[40]; tm = localtime_r(&timeval, &s_tm); - strftime(sCurrentTime, sizeof(sCurrentTime),"%Y-%m-%d %H:%M:%S",tm); + len = strftime(sCurrentTime, sizeof(sCurrentTime), "%Y-%m-%d %H:%M:%S", tm); + if (len == 0) *sCurrentTime = '\0'; tm->tm_sec = tm->tm_min = 0; if (data->reset == NULL) return -1; if (isdigit((int) data->reset[0])){ - unsigned int len=0; - len = strlen(data->reset); if (len == 0) return -1; @@ -300,9 +294,11 @@ static int find_next_reset(rlm_counter_t *data, time_t timeval) data->reset); return -1; } - strftime(sNextTime, sizeof(sNextTime),"%Y-%m-%d %H:%M:%S",tm); - DEBUG2("rlm_counter: Current Time: %d [%s], Next reset %d [%s]", - (int)timeval,sCurrentTime,(int)data->reset_time,sNextTime); + + len = strftime(sNextTime, sizeof(sNextTime), "%Y-%m-%d %H:%M:%S", tm); + if (len == 0) *sNextTime = '\0'; + DEBUG2("rlm_counter: Current Time: %li [%s], Next reset %li [%s]", + timeval, sCurrentTime, data->reset_time, sNextTime); return ret; } @@ -387,25 +383,25 @@ static int counter_instantiate(CONF_SECTION *conf, void **instance) data->count_attr = dattr->attr; /* - * Discover the attribute number of the return attribute. + * Discover the attribute number of the reply attribute. */ - if (data->return_attribute != NULL) { - dattr = dict_attrbyname(data->return_attribute); + if (data->reply_name != NULL) { + dattr = dict_attrbyname(data->reply_name); if (dattr == NULL) { radlog(L_ERR, "rlm_counter: No such attribute %s", - data->return_attribute); + data->reply_name); counter_detach(data); return -1; } if (dattr->type != PW_TYPE_INTEGER) { - radlog(L_ERR, "rlm_counter: Return attribute %s is not of type integer", - data->return_attribute); + radlog(L_ERR, "rlm_counter: Reply attribute %s is not of type integer", + data->reply_name); counter_detach(data); return -1; } - data->return_attr = dattr->attr; + data->reply_attr = dattr->attr; } - + /* * Create a new attribute for the counter. @@ -417,7 +413,7 @@ static int counter_instantiate(CONF_SECTION *conf, void **instance) } memset(&flags, 0, sizeof(flags)); - dict_addattr(data->counter_name, 0, PW_TYPE_INTEGER, -1, flags); + dict_addattr(data->counter_name, -1, 0, PW_TYPE_INTEGER, flags); dattr = dict_attrbyname(data->counter_name); if (dattr == NULL) { radlog(L_ERR, "rlm_counter: Failed to create counter attribute %s", @@ -451,7 +447,7 @@ static int counter_instantiate(CONF_SECTION *conf, void **instance) * Find the attribute for the allowed protocol */ if (data->service_type != NULL) { - if ((dval = dict_valbyname(PW_SERVICE_TYPE, data->service_type)) == NULL) { + if ((dval = dict_valbyname(PW_SERVICE_TYPE, 0, data->service_type)) == NULL) { radlog(L_ERR, "rlm_counter: Failed to find attribute number for %s", data->service_type); counter_detach(data); @@ -576,8 +572,8 @@ static int counter_accounting(void *instance, REQUEST *request) int acctstatustype = 0; time_t diff; - if ((key_vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) - acctstatustype = key_vp->lvalue; + if ((key_vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0)) != NULL) + acctstatustype = key_vp->vp_integer; else { DEBUG("rlm_counter: Could not find account status type in packet."); return RLM_MODULE_NOOP; @@ -586,9 +582,9 @@ static int counter_accounting(void *instance, REQUEST *request) DEBUG("rlm_counter: We only run on Accounting-Stop packets."); return RLM_MODULE_NOOP; } - uniqueid_vp = pairfind(request->packet->vps, PW_ACCT_UNIQUE_SESSION_ID); + uniqueid_vp = pairfind(request->packet->vps, PW_ACCT_UNIQUE_SESSION_ID, 0); if (uniqueid_vp != NULL) - DEBUG("rlm_counter: Packet Unique ID = '%s'",uniqueid_vp->strvalue); + DEBUG("rlm_counter: Packet Unique ID = '%s'",uniqueid_vp->vp_strvalue); /* * Before doing anything else, see if we have to reset @@ -610,11 +606,11 @@ static int counter_accounting(void *instance, REQUEST *request) * Check if we need to watch out for a specific service-type. If yes then check it */ if (data->service_type != NULL) { - if ((proto_vp = pairfind(request->packet->vps, PW_SERVICE_TYPE)) == NULL){ + if ((proto_vp = pairfind(request->packet->vps, PW_SERVICE_TYPE, 0)) == NULL){ DEBUG("rlm_counter: Could not find Service-Type attribute in the request. Returning NOOP."); return RLM_MODULE_NOOP; } - if ((unsigned)proto_vp->lvalue != data->service_val){ + if ((unsigned)proto_vp->vp_integer != data->service_val){ DEBUG("rlm_counter: This Service-Type is not allowed. Returning NOOP."); return RLM_MODULE_NOOP; } @@ -623,10 +619,10 @@ static int counter_accounting(void *instance, REQUEST *request) * Check if request->timestamp - {Acct-Delay-Time} < last_reset * If yes reject the packet since it is very old */ - key_vp = pairfind(request->packet->vps, PW_ACCT_DELAY_TIME); + key_vp = pairfind(request->packet->vps, PW_ACCT_DELAY_TIME, 0); if (key_vp != NULL){ - if (key_vp->lvalue != 0 && - (request->timestamp - key_vp->lvalue) < data->last_reset){ + if (key_vp->vp_integer != 0 && + (request->timestamp - key_vp->vp_integer) < data->last_reset){ DEBUG("rlm_counter: This packet is too old. Returning NOOP."); return RLM_MODULE_NOOP; } @@ -638,7 +634,7 @@ static int counter_accounting(void *instance, REQUEST *request) * Look for the key. User-Name is special. It means * The REAL username, after stripping. */ - key_vp = (data->key_attr == PW_USER_NAME) ? request->username : pairfind(request->packet->vps, data->key_attr); + key_vp = (data->key_attr == PW_USER_NAME) ? request->username : pairfind(request->packet->vps, data->key_attr, 0); if (key_vp == NULL){ DEBUG("rlm_counter: Could not find the key-attribute in the request. Returning NOOP."); return RLM_MODULE_NOOP; @@ -647,16 +643,16 @@ static int counter_accounting(void *instance, REQUEST *request) /* * Look for the attribute to use as a counter. */ - count_vp = pairfind(request->packet->vps, data->count_attr); + count_vp = pairfind(request->packet->vps, data->count_attr, 0); if (count_vp == NULL){ DEBUG("rlm_counter: Could not find the count-attribute in the request."); return RLM_MODULE_NOOP; } - key_datum.dptr = key_vp->strvalue; + key_datum.dptr = key_vp->vp_strvalue; key_datum.dsize = key_vp->length; - DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->strvalue); + DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->vp_strvalue); pthread_mutex_lock(&data->mutex); count_datum = gdbm_fetch(data->gdbm, key_datum); pthread_mutex_unlock(&data->mutex); @@ -664,7 +660,8 @@ static int counter_accounting(void *instance, REQUEST *request) DEBUG("rlm_counter: Could not find the requested key in the database."); counter.user_counter = 0; if (uniqueid_vp != NULL) - strncpy(counter.uniqueid,uniqueid_vp->strvalue,UNIQUEID_MAX_LEN - 1); + strlcpy(counter.uniqueid,uniqueid_vp->vp_strvalue, + sizeof(counter.uniqueid)); else memset((char *)counter.uniqueid,0,UNIQUEID_MAX_LEN); } @@ -676,13 +673,14 @@ static int counter_accounting(void *instance, REQUEST *request) DEBUG("rlm_counter: Counter Unique ID = '%s'",counter.uniqueid); if (uniqueid_vp != NULL){ if (counter.uniqueid != NULL && - strncmp(uniqueid_vp->strvalue,counter.uniqueid, UNIQUEID_MAX_LEN - 1) == 0){ + strncmp(uniqueid_vp->vp_strvalue,counter.uniqueid, UNIQUEID_MAX_LEN - 1) == 0){ DEBUG("rlm_counter: Unique IDs for user match. Droping the request."); return RLM_MODULE_NOOP; } - strncpy(counter.uniqueid,uniqueid_vp->strvalue,UNIQUEID_MAX_LEN - 1); + strlcpy(counter.uniqueid,uniqueid_vp->vp_strvalue, + sizeof(counter.uniqueid)); } - DEBUG("rlm_counter: User=%s, Counter=%d.",request->username->strvalue,counter.user_counter); + DEBUG("rlm_counter: User=%s, Counter=%d.",request->username->vp_strvalue,counter.user_counter); } if (data->count_attr == PW_ACCT_SESSION_TIME) { @@ -697,14 +695,14 @@ static int counter_accounting(void *instance, REQUEST *request) * day). That is the right thing */ diff = request->timestamp - data->last_reset; - counter.user_counter += (count_vp->lvalue < diff) ? count_vp->lvalue : diff; + counter.user_counter += (count_vp->vp_integer < diff) ? count_vp->vp_integer : diff; } else if (count_vp->type == PW_TYPE_INTEGER) { /* * Integers get counted, without worrying about * reset dates. */ - counter.user_counter += count_vp->lvalue; + counter.user_counter += count_vp->vp_integer; } else { /* @@ -714,7 +712,7 @@ static int counter_accounting(void *instance, REQUEST *request) counter.user_counter++; } - DEBUG("rlm_counter: User=%s, New Counter=%d.",request->username->strvalue,counter.user_counter); + DEBUG("rlm_counter: User=%s, New Counter=%d.",request->username->vp_strvalue,counter.user_counter); count_datum.dptr = (char *) &counter; count_datum.dsize = sizeof(rad_counter); @@ -776,7 +774,7 @@ static int counter_authorize(void *instance, REQUEST *request) * The REAL username, after stripping. */ DEBUG2("rlm_counter: Entering module authorize code"); - key_vp = (data->key_attr == PW_USER_NAME) ? request->username : pairfind(request->packet->vps, data->key_attr); + key_vp = (data->key_attr == PW_USER_NAME) ? request->username : pairfind(request->packet->vps, data->key_attr, 0); if (key_vp == NULL) { DEBUG2("rlm_counter: Could not find Key value pair"); return ret; @@ -785,12 +783,12 @@ static int counter_authorize(void *instance, REQUEST *request) /* * Look for the check item */ - if ((check_vp= pairfind(request->config_items, data->check_attr)) == NULL) { + if ((check_vp= pairfind(request->config_items, data->check_attr, 0)) == NULL) { DEBUG2("rlm_counter: Could not find Check item value pair"); return ret; } - key_datum.dptr = key_vp->strvalue; + key_datum.dptr = key_vp->vp_strvalue; key_datum.dsize = key_vp->length; @@ -800,7 +798,7 @@ static int counter_authorize(void *instance, REQUEST *request) counter.user_counter = 0; - DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->strvalue); + DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->vp_strvalue); pthread_mutex_lock(&data->mutex); count_datum = gdbm_fetch(data->gdbm, key_datum); pthread_mutex_unlock(&data->mutex); @@ -815,8 +813,8 @@ static int counter_authorize(void *instance, REQUEST *request) /* * Check if check item > counter */ - DEBUG("rlm_counter: Check item = %d, Count = %d",check_vp->lvalue,counter.user_counter); - res=check_vp->lvalue - counter.user_counter; + DEBUG("rlm_counter: Check item = %d, Count = %d",check_vp->vp_integer,counter.user_counter); + res=check_vp->vp_integer - counter.user_counter; if (res > 0) { DEBUG("rlm_counter: res is greater than zero"); if (data->count_attr == PW_ACCT_SESSION_TIME) { @@ -847,33 +845,25 @@ static int counter_authorize(void *instance, REQUEST *request) if (data->reset_time && ( res >= (data->reset_time - request->timestamp))) { res = data->reset_time - request->timestamp; - res += check_vp->lvalue; + res += check_vp->vp_integer; } - if ((reply_item = pairfind(request->reply->vps, PW_SESSION_TIMEOUT)) != NULL) { - if (reply_item->lvalue > res) - reply_item->lvalue = res; + if ((reply_item = pairfind(request->reply->vps, PW_SESSION_TIMEOUT, 0)) != NULL) { + if (reply_item->vp_integer > res) + reply_item->vp_integer = res; } else { - if ((reply_item = paircreate(PW_SESSION_TIMEOUT, PW_TYPE_INTEGER)) == NULL) { - radlog(L_ERR|L_CONS, "no memory"); - return RLM_MODULE_NOOP; - } - reply_item->lvalue = res; - pairadd(&request->reply->vps, reply_item); + reply_item = radius_paircreate(request, &request->reply->vps, PW_SESSION_TIMEOUT, 0, PW_TYPE_INTEGER); + reply_item->vp_integer = res; } } - else if (data->return_attr) { - if ((reply_item = pairfind(request->reply->vps, data->return_attr)) != NULL) { - if (reply_item->lvalue > res) - reply_item->lvalue = res; + else if (data->reply_attr) { + if ((reply_item = pairfind(request->reply->vps, data->reply_attr, 0)) != NULL) { + if (reply_item->vp_integer > res) + reply_item->vp_integer = res; } else { - if ((reply_item = paircreate(data->return_attr, PW_TYPE_INTEGER)) == NULL) { - radlog(L_ERR|L_CONS, "no memory"); - return RLM_MODULE_NOOP; - } - reply_item->lvalue = res; - pairadd(&request->reply->vps, reply_item); + reply_item = radius_paircreate(request, &request->reply->vps, data->reply_attr, 0, PW_TYPE_INTEGER); + reply_item->vp_integer = res; } } @@ -881,9 +871,9 @@ static int counter_authorize(void *instance, REQUEST *request) DEBUG2("rlm_counter: (Check item - counter) is greater than zero"); DEBUG2("rlm_counter: Authorized user %s, check_item=%d, counter=%d", - key_vp->strvalue,check_vp->lvalue,counter.user_counter); + key_vp->vp_strvalue,check_vp->vp_integer,counter.user_counter); DEBUG2("rlm_counter: Sent Reply-Item for user %s, Type=Session-Timeout, value=%d", - key_vp->strvalue,res); + key_vp->vp_strvalue,res); } else{ char module_fmsg[MAX_STRING_LEN]; @@ -903,7 +893,7 @@ static int counter_authorize(void *instance, REQUEST *request) ret=RLM_MODULE_REJECT; DEBUG2("rlm_counter: Rejected user %s, check_item=%d, counter=%d", - key_vp->strvalue,check_vp->lvalue,counter.user_counter); + key_vp->vp_strvalue,check_vp->vp_integer,counter.user_counter); } return ret; @@ -916,13 +906,6 @@ static int counter_detach(void *instance) paircompare_unregister(data->dict_attr, counter_cmp); if (data->gdbm) gdbm_close(data->gdbm); - free(data->filename); - free(data->reset); - free(data->key_name); - free(data->count_attribute); - free(data->counter_name); - free(data->check_name); - free(data->service_type); pthread_mutex_destroy(&data->mutex); free(instance); @@ -939,10 +922,11 @@ static int counter_detach(void *instance) * is single-threaded. */ module_t rlm_counter = { - "Counter", + RLM_MODULE_INIT, + "counter", RLM_TYPE_THREAD_SAFE, /* type */ - NULL, /* initialization */ counter_instantiate, /* instantiation */ + counter_detach, /* detach */ { NULL, /* authentication */ counter_authorize, /* authorization */ @@ -953,6 +937,4 @@ module_t rlm_counter = { NULL, /* post-proxy */ NULL /* post-auth */ }, - counter_detach, /* detach */ - NULL, /* destroy */ };