4 * This program is is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 if the
6 * License as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 * Copyright 2000 The FreeRADIUS server project
21 #include "libradius.h"
29 #define BUFFERLEN 2048
31 static const char rcsid[] = "$Id$";
33 typedef struct unique_attr_list {
35 struct unique_attr_list *next;
38 typedef struct unique_config_t {
40 struct unique_attr_list *head;
43 static unique_config_t config;
45 static CONF_PARSER module_config[] = {
46 { "key", PW_TYPE_STRING_PTR, &config.key, NULL },
47 { NULL, -1, NULL, NULL } /* end the list */
51 * Add an attribute to the list.
53 static void unique_add_attr(int dictattr) {
54 struct unique_attr_list *new;
56 if((new = malloc(sizeof(struct unique_attr_list))) == NULL) {
57 radlog(L_ERR, "rlm_acct_unique: out of memory");
60 memset((struct unique_attr_list *)new, 0, sizeof(unique_attr_list));
62 /* Assign the attr to our new structure */
66 new->next = config.head;
76 static int unique_parse_key(char *key) {
77 char *ptr, *prev, *keyptr;
84 /* Let's remove spaces in the string */
92 if((a = dict_attrbyname(prev)) == NULL) {
93 radlog(L_ERR, "rlm_acct_unique: Cannot find attribute '%s' in dictionary", prev);
98 unique_add_attr(a->attr);
101 if((a = dict_attrbyname(prev)) == NULL) {
102 radlog(L_ERR, "rlm_acct_unique: Cannot find attribute '%s' in dictionary", prev);
105 unique_add_attr(a->attr);
118 static int unique_instantiate(CONF_SECTION *conf, void **instance) {
120 struct unique_config_t *inst;
123 * Set up a storage area for instance data
125 if ((inst = malloc(sizeof(*inst))) == NULL) {
126 radlog(L_ERR, "rlm_acct_unique: out of memory");
129 memset(inst, 0, sizeof(*inst));
131 if (cf_section_parse(conf, module_config) < 0) {
139 inst->key = config.key;
143 * Check to see if 'key' has something in it
146 radlog(L_ERR,"rlm_acct_unique: Cannot find value for 'key' in configuration.");
151 * Go thru the list of keys and build attr_list;
153 if (unique_parse_key(inst->key) < 0) {
157 inst->head = config.head;
164 * Create a (hopefully) unique Acct-Unique-Session-Id from
165 * attributes listed in 'key' from radiusd.conf
167 static int unique_accounting(void *instance, REQUEST *request)
169 char buffer[BUFFERLEN];
175 struct unique_config_t *inst = instance;
176 struct unique_attr_list *cur;
178 /* initialize variables */
184 /* loop over items to create unique identifiers */
186 vp = pairfind(request->packet->vps, cur->attr);
187 length = vp_prints(p, left, vp);
188 left -= length + 1; /* account for ',' in between elements */
190 *(p++) = ','; /* ensure seperation of elements */
193 buffer[BUFFERLEN-left-1] = '\0';
195 DEBUG2("rlm_acct_unique: Hashing '%s'", buffer);
196 /* calculate a 'unique' string based on the above information */
197 librad_md5_calc(md5_buf, (u_char *)buffer, (p - buffer));
198 sprintf(buffer, "%02x%02x%02x%02x%02x%02x%02x%02x",
199 md5_buf[0], md5_buf[1], md5_buf[2], md5_buf[3],
200 md5_buf[4], md5_buf[5], md5_buf[6], md5_buf[7]);
202 DEBUG2("rlm_acct_unique: Acct-Unique-Session-ID = \"%s\".", buffer);
204 vp = pairmake("Acct-Unique-Session-Id", buffer, 0);
206 radlog(L_ERR, "%s", librad_errstr);
207 return RLM_MODULE_FAIL;
210 /* add the (hopefully) unique session ID to the packet */
211 pairadd(&request->packet->vps, vp);
213 /* FIXME: Uncomment here once we iron out module_accounting() */
214 /*return RLM_MODULE_UPDATED;*/
215 return RLM_MODULE_OK;
218 static int unique_detach(void *instance) {
219 struct unique_config_t *inst = instance;
220 struct unique_attr_list *next = inst->head;
224 next = inst->head->next;
225 DEBUG("HERE: %d", inst->head->attr);
234 /* FIXME: unique_accounting should probably be called from preacct */
235 /* globally exported name */
236 module_t rlm_acct_unique = {
237 "Acct-Unique-Session-Id",
238 0, /* type: reserved */
239 NULL, /* initialization */
240 unique_instantiate, /* instantiation */
241 NULL, /* authorization */
242 NULL, /* authentication */
243 NULL, /* preaccounting */
244 unique_accounting, /* accounting */
245 NULL, /* checksimul */
246 unique_detach, /* detach */